Browse Source

smd-client/server: refactoring and new options

Enrico Tassi 8 years ago
parent
commit
661fb3eed3
5 changed files with 151 additions and 20 deletions
  1. 71
    1
      smd-client
  2. 7
    1
      smd-client.1.txt
  3. 47
    10
      smd-server
  4. 8
    4
      smd-server.1.txt
  5. 18
    4
      syncmaildir.lua

+ 71
- 1
smd-client View File

@@ -139,6 +139,48 @@ function get_header_and_merge(name,hsha)
139 139
 	end
140 140
 end
141 141
 
142
+-- ============================= renaming ====================================
143
+
144
+function compute_renamings(actions)
145
+	local copy = {}
146
+	local delete = {}
147
+	local script = {}
148
+	for _, cmd in ipairs(actions) do
149
+		local opcode = parse(cmd, '^(%S+)')
150
+		if opcode == "COPY" then
151
+			local name_src, hsha, bsha, name_tgt = 
152
+				parse(cmd, '^COPY (%S+) (%S+) (%S+) TO (%S+)$')
153
+			name_src = url_decode(name_src)
154
+			name_tgt = url_decode(name_tgt)
155
+			copy[#copy + 1] = { src = name_src, tgt = name_tgt}
156
+		elseif opcode == "DELETE" then
157
+			local name, hsha, bsha = parse(cmd, '^DELETE (%S+) (%S+) (%S+)$')
158
+			name = url_decode(name)
159
+			delete[name] = true
160
+		end
161
+	end
162
+	for _, cp in ipairs(copy) do
163
+		-- it is a real move
164
+		if delete[cp.src] then
165
+			local absolute1, t1, last1 = tokenize_path(cp.src)
166
+			local absolute2, t2, last2 = tokenize_path(cp.tgt)
167
+			local dir1 = table.concat(t1,'/')
168
+			local dir2 = table.concat(t2,'/')
169
+			if not absolute1 and not absolute2 and 
170
+				last1 ~= nil and last2 ~= nil and
171
+				(t1[#t1] == "cur" or t1[#t1] == "new") and
172
+				(t2[#t2] == "cur" or t2[#t2] == "new") and
173
+				dir1 == dir2 and is_translator_set() then
174
+				local t_dir =  homefy(translate(dir1))
175
+				script[#script + 1] = string.format( "mv %s %s",
176
+					quote(t_dir..'/'..last1),
177
+					quote(t_dir..'/'..last2))
178
+			end
179
+		end
180
+	end
181
+	return script
182
+end
183
+
142 184
 -- ============================= actions =====================================
143 185
 
144 186
 function execute_add(name, hsha, bsha)
@@ -489,6 +531,8 @@ function main()
489 531
 	local usage = "Usage: "..arg[0]:match('[^/]+$')..
490 532
 		" [-vd] [-t translatorRL] endpointname mailboxes...\n"
491 533
 	local apply_xdelta = true
534
+	local rename_only = false
535
+	local override_db = nil
492 536
 	while #arg > 2 do
493 537
 		if arg[1] == '-v' or arg[1] == '--verbose' then
494 538
 			set_verbose(true)
@@ -503,6 +547,13 @@ function main()
503 547
 			set_translator(arg[2])
504 548
 			table.remove(arg,1)
505 549
 			table.remove(arg,1)
550
+		elseif arg[1] == '--rename-only' then
551
+			rename_only = true
552
+			table.remove(arg,1)
553
+		elseif arg[1] == '--override-db' then
554
+			override_db = arg[2]
555
+			table.remove(arg,1)
556
+			table.remove(arg,1)
506 557
 		else
507 558
 			break
508 559
 		end
@@ -516,7 +567,12 @@ function main()
516 567
 	-- here we go
517 568
 	local endpoint = arg[1]
518 569
 	table.remove(arg,1)
519
-	local dbfile = dbfile_name(endpoint, arg)
570
+	local dbfile = nil
571
+	if override_db ~= nil then
572
+		dbfile = override_db:gsub('^~',os.getenv('HOME'))
573
+	else
574
+		dbfile = dbfile_name(endpoint, arg)
575
+	end
520 576
 	local xdelta = dbfile .. '.xdelta'
521 577
 	local newdb = dbfile .. '.new'
522 578
 	
@@ -542,6 +598,20 @@ function main()
542 598
 	
543 599
 	-- receive and process commands
544 600
 	local commands = receive_delta(io.stdin, firsttime)
601
+	if rename_only then
602
+			-- in renaming mode, we handle commands in a peculiar way
603
+			log_progress('Phase 2: renaming script generation')
604
+			local script = compute_renamings(commands)
605
+			local fname = os.getenv('HOME')..'/smd-rename.sh'
606
+			local f = io.open(fname,'w')
607
+			f:write('#!/bin/sh\n\n')
608
+			f:write(table.concat(script,'\n'))
609
+			f:close()
610
+			log('Please check and run: '..fname)
611
+			-- and we exit
612
+			os.exit(0)
613
+	end
614
+
545 615
 	log_progress('Phase 2: synchronization')
546 616
 	if firsttime then
547 617
 		log_progress([[

+ 7
- 1
smd-client.1.txt View File

@@ -2,7 +2,9 @@ NAME
2 2
   smd-client - receives diffs and performs actions
3 3
 
4 4
 SYNOPSIS
5
-  smd-client [-v|--verbose] [-d|--dry-run] [-t|--translator] endpoint mailboxes
5
+  smd-client [-v|--verbose] [-d|--dry-run] [-t|--translator]
6
+	[-l|--local-sync] [--rename-only]
7
+	[--override-db dbf] endpoint mailboxes
6 8
 
7 9
 DESCRIPTION
8 10
   smd-client needs to know a name (endpoint) for the client (that must not
@@ -18,6 +20,10 @@ OPTIONS
18 20
                    program) is optimized away
19 21
   -l --local-sync  Local synchronization, no changes is made to the db-file
20 22
                    since smd-server takes care of it
23
+  --rename-only    Do not synchronize the mailboxes but generate the 
24
+                   script '~/smd-rename.sh' to uniform the files names in the
25
+                   mailbox
26
+  --override-db dbf  Use dbf as the db-file
21 27
   -v --verbose     Increase program verbosity (printed on stderr)
22 28
   -d --dry-run     Do not perform any action for real
23 29
 

+ 47
- 10
smd-server View File

@@ -20,7 +20,9 @@ function main()
20 20
 	local exclude = {}
21 21
 	local no_delete = false
22 22
 	local just_mddiff = false
23
-	local just_dbfile = false
23
+	local stop_after_diff = false
24
+	local override_db = nil
25
+	local dump_stdin_to = nil
24 26
 	local usage = "Usage: "..arg[0]:match('[^/]+$')..
25 27
 		" [-vdn] endpointname mailboxes...\n"
26 28
 	while #arg > 2 do
@@ -38,11 +40,19 @@ function main()
38 40
 			exclude[#exclude + 1] = arg[2]
39 41
 			table.remove(arg,1)
40 42
 			table.remove(arg,1)
41
-		elseif arg[1] == '--just-print-mddiff-cmdline' then
43
+		elseif arg[1] == '--get-mddiff-cmdline' then
42 44
 			just_mddiff = true
43 45
 			table.remove(arg,1)
44
-		elseif arg[1] == '--just-print-db-filename' then
45
-			just_dbfile = true
46
+		elseif arg[1] == '--override-db' then
47
+			override_db = arg[2]
48
+			table.remove(arg,1)
49
+			table.remove(arg,1)
50
+		elseif arg[1] == '--stop-after-diff' then
51
+			stop_after_diff = true
52
+			table.remove(arg,1)
53
+		elseif arg[1] == '--dump-stdin' then
54
+			dump_stdin_to = arg[2]
55
+			table.remove(arg,1)
46 56
 			table.remove(arg,1)
47 57
 		else
48 58
 			break
@@ -54,9 +64,27 @@ function main()
54 64
 		os.exit(2)
55 65
 	end
56 66
 
67
+	if dump_stdin_to ~= nil then
68
+		dump_stdin_to = dump_stdin_to:gsub('^~',os.getenv('HOME'))
69
+		mkdir_p(dump_stdin_to)
70
+		local f = io.open(dump_stdin_to,'w')
71
+		local data = nil
72
+		repeat
73
+				data = io.read(4096)
74
+				if data then f:write(data) end
75
+		until data == nil
76
+		f:close()
77
+		os.exit(0)
78
+	end
79
+
57 80
 	local endpoint = arg[1]
58 81
 	table.remove(arg,1)
59
-	local dbfile = dbfile_name(endpoint, arg)
82
+	local dbfile = nil
83
+	if override_db ~= nil then
84
+		dbfile = override_db:gsub('^~',os.getenv('HOME'))
85
+	else
86
+		dbfile = dbfile_name(endpoint, arg)
87
+	end
60 88
 	local xdelta = dbfile .. '.xdelta'
61 89
 	local dbfilemt = dbfile .. '.mtime'
62 90
 	local newdb = dbfile .. '.new'
@@ -72,12 +100,10 @@ function main()
72 100
 	local mddiff = MDDIFF..' '..dry_opt..' '..database_opt..' '..
73 101
 		exclude_opt..' '..no_delete_opt..' '..mailbox_opt
74 102
 	
103
+	-- to call mddiff from another tool with the same cmdline
75 104
 	if just_mddiff then
76
-			print(mddiff)
77
-			os.exit(0)
78
-	elseif just_dbfile then
79
-			print(dbfile)
80
-			os.exit(0)
105
+		print(mddiff)
106
+		os.exit(0)
81 107
 	end
82 108
 
83 109
 
@@ -103,6 +129,17 @@ function main()
103 129
 	-- of some data
104 130
 	io.write('END\n')
105 131
 	io.flush()
132
+
133
+	-- if renaming mode, we exit
134
+	if stop_after_diff then
135
+		if override_db ~= nil then
136
+			os.remove(dbfile)
137
+			os.remove(dbfilemt)
138
+			os.remove(newdb)
139
+			os.remove(newdbmt)
140
+		end
141
+		os.exit(0)
142
+	end
106 143
 	
107 144
 	-- process client commands
108 145
 	while true do

+ 8
- 4
smd-server.1.txt View File

@@ -3,8 +3,8 @@ NAME
3 3
 
4 4
 SYNOPSIS
5 5
   smd-server [--exclude glob] [-v|--verbose] [-d|--dry-run]
6
-	[--just-print-mddiff-cmdline]
7
-	[--just-print-db-filename] endpoint mailboxes
6
+	[--get-mddiff-cmdline] [--stop-after-diff]
7
+	[--override-db dbf] [--dump-stdin tgt] endpoint mailboxes
8 8
 
9 9
 DESCRIPTION
10 10
   smd-server needs to know a name (endpoint) for the client (that must not
@@ -22,8 +22,12 @@ OPTIONS
22 22
   -d --dry-run    Do not perform any action for real
23 23
   -n --no-delete  Do not track deleted files
24 24
   --exclude glob  Exclude paths matching glob
25
-  --just-print-mddiff-cmdline  Prints the command like used for mddiff and then exists
26
-  --just-print-db-filename  Prints the db-file name and then exists
25
+  --override-db dbf  Use dbf as the db-file
26
+  --get-mddiff-cmdline  Print the command line used for mddiff and then exist
27
+  --stop-after-diff  Send the actions to the other endpoint and exit. If used
28
+                     in conjunction with --override-db, dbf is removed just
29
+                     before exiting
30
+  --dump-stdin tgt  Dump standard input to tgt and exit
27 31
 
28 32
 NOTES
29 33
   smd-server is a low level utility. You should use higher level tools like

+ 18
- 4
syncmaildir.lua View File

@@ -372,26 +372,34 @@ function make_dir_aux(absolute, pieces)
372 372
 	end
373 373
 end
374 374
 
375
-function mkdir_p(path)
375
+function tokenize_path(path)
376 376
 	local t = {} 
377
-
378 377
 	local absolute = false
378
+	local file = ""
379
+
379 380
 	if string.byte(path,1) == string.byte('/',1) then absolute = true end
380 381
 
381 382
 	-- tokenization
382 383
 	for m in path:gmatch('([^/]+)') do t[#t+1] = m end
383 384
 
384
-	-- strip last component is not ending with '/'
385
-	if string.byte(path,string.len(path)) ~= string.byte('/',1) then 
385
+	-- strip last component if not ending with '/'
386
+	if string.byte(path,string.len(path)) ~= string.byte('/',1) then
387
+		file=t[#t]
386 388
 		table.remove(t,#t) 
387 389
 	end
388 390
 
391
+	return absolute, t, file
392
+end
393
+
394
+-- creates a directory that can contains a path, should be equivalent
395
+-- to mkdir -p `dirname path`. moreover, if the last component is 'tmp',
396
+-- 'cur' or 'new', they are all are created too. exampels:
397
+--  mkdir_p('/foo/bar')     creates /foo
398
+--  mkdir_p('/foo/bar/')    creates /foo/bar/
399
+--  mkdir_p('/foo/tmp/baz') creates /foo/tmp/, /foo/cur/ and /foo/new/
400
+function mkdir_p(path)
401
+	local absolute, t, _ = tokenize_path(path)
402
+
389 403
 	make_dir_aux(absolute, t)
390 404
 
391 405
 	--  ensure new, tmp and cur are there

Loading…
Cancel
Save