-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathsyncdiff.r
executable file
·202 lines (186 loc) · 4.8 KB
/
syncdiff.r
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#!/usr/local/bin/rexx
/*#!/data/data/com.termux/files/home/bin/rexx*/
/* Compare two sync files and create a diff file with all files and a flag on the change
* diff file format
* <flag> <unixtime> <size> <user> <group> <filename>
* flag:
* f - regular file no change since last time
* D - regular directory no change
* n - new file
* N - new directory
* c - file changed since last time
* e - erased(deleted) file
* E - erased(deleted) directory (with all subdirs and files)
* i - ignored file
* I - ignored directory
*
* return on stdout the location of the temporary file created
*/
parse arg host conffile filediff
if host="" | conffile="" | filediff="" then call usage
if host=='local' then
mode = "l"
else
mode = 'r'
call load "synclib.r"
if result != 0 then
call load "/usr/local/lib/brexx/synclib.r"
/*call load "/home/bnv/prg/synchronize/synclib.r"*/
call SyncConfig
filenew = TMP"/_sync."host
fileold = SYNCPATH||host
FILEINFO "-"mode "-o "filenew conffile
if rc<>0 then do
call lineout "<STDERR>","Error getting file information RC="RC
exit rc
end
fc = open(conffile,"r")
fdiff = open(filediff,"w")
do forever
line = strip(read(fc))
if eof(fc) then leave
start = left(line,1)
if start=="#" | start=="@" | start=="-" | line=="" then iterate
if abbrev(line,"local:") & mode=='l' then do
parse var line . ":" base
base = strip(base)
if right(base,1)=="/" then base = left(base, length(base)-1)
hash = CompareFiles(strip(base))
end; else
if abbrev(line,"remote:") & mode=='r' then do
parse var line . ":" base
base = strip(base)
if right(base,1)=="/" then base = left(base, length(base)-1)
hash = CompareFiles(base)
end
end
call close fc
call close fdiff
"rm -f" filenew".*"
return
/* --- Usage --- */
Usage:
parse source . . prg .
say "syntax:" prg "{local|host} <config-file>"
exit
/* --- CompareFiles --- */
CompareFiles: procedure expose filenew fileold fdiff
parse arg base
hash = right(d2x(HashValue(base)),8,0)
fnew = open(filenew"."hash,"r")
fold = open(fileold"."hash,"r")
if fnew<0 then do
say "ERROR:" fnew "opening file new="filenew"."hash
exit
return hash
end
basenew = read(fnew)
call lineout fdiff,basenew
if fold>0 then do
baseold = read(fold)
if basenew ^= baseold then do
say "Error reading new/old files"
say "New="filenew"."hash "("fnew")" basenew
say "Old="fileold"."hash "("fold")" baseold
signal CMP_END
end
call ReadDir fnew,"new.","basenew"
call ReadDir fold,"old.","baseold"
do while new.0>0 & old.0>0
if new.1 ^== old.1 then do
if new.1<old.1 then do
call PrintDirInfo 'n'
call ReadDir fnew,"new.","basenew"
end; else do
call PrintDirInfo 'e'
call ReadDir fold,"old.","baseold"
end
end; else do
if new.1.@TYPE ^== 'I' then
call CheckDirectories
call ReadDir fnew,"new.","basenew"
call ReadDir fold,"old.","baseold"
end
end
do while new.0>0
call PrintDirInfo 'n'
call ReadDir fnew,"new.","basenew"
end
do while old.0>0
call PrintDirInfo 'e'
call ReadDir fold,"old.","baseold"
end
end; else do
call ReadDir fnew,"new.","basenew"
do while new.0>0
call PrintDirInfo 'f'
call ReadDir fnew,"new.","basenew"
end
end
CMP_END:
call close fnew
if fold>0 then call close fold
return hash
/* --- CheckDirectories --- */
CheckDirectories:
/* the directories names are the same */
call lineout fdiff,'D' new.1.@INFO new.1
n=2; o=2
do while n<=new.0 & o<=old.0
if new.n==old.o then do
if new.n.@TYPE^=='i' then do
if new.n.@INFO ^== old.o.@INFO then
type = 'c' /* changed */
else
type = new.n.@TYPE
call lineout fdiff,type new.n.@INFO new.n
end
n=n+1
o=o+1
end; else
if new.n<old.o then do
if new.n.@TYPE^=='i' then
call lineout fdiff,'n' new.n.@INFO new.n /* new */
n=n+1
end; else do
if old.o.@TYPE^=='i' then
call lineout fdiff,'e' old.o.@INFO old.o /* deleted */
o=o+1
end
end
/* Check remaining files */
if n<=new.0 then
do n=n to new.0
if new.n.@TYPE^=='i' then
call lineout fdiff,'n' new.n.@INFO new.n /* new */
end
if o<=old.0 then
do o=o to old.0
if old.o.@TYPE^=='i' then
call lineout fdiff,'e' old.o.@INFO old.o /* erased */
end
return
/* --- PrintDirInfo --- */
PrintDirInfo:
parse arg _action
if _action=='n' | _action=='f' then do
if _action=='n' then
_diraction='N'
else
_diraction='D'
if new.1.@TYPE=='I' then
call lineout fdiff,'I' new.1.@INFO new.1 /* ignore */
else do
call lineout fdiff,_diraction new.1.@INFO new.1 /* new dir */
do n=2 to new.0
if new.n.@TYPE^='i' then
call lineout fdiff,_action new.n.@INFO new.n /* new */
end
end
end; else do
if old.1.@TYPE=='I' then
call lineout fdiff, 'I' old.1.@INFO old.1 /* ignore */
else
call lineout fdiff, 'E' old.1.@INFO old.1 /* erased with sub dirs */
end
return