1 Depends-On-Patch: partial-dir.diff
2 Depends-On-Patch: g2r-basis-filename.diff
4 The changes to generator.c were greatly simplified, making the patch
5 easier to maintain and fixing the failing test in the testsuite.
8 Be sure to run "make proto" before "make".
10 --- orig/generator.c 2004-07-28 10:14:15
11 +++ generator.c 2004-07-28 10:23:12
12 @@ -41,6 +41,7 @@ extern int ignore_times;
14 extern int io_timeout;
15 extern int protocol_version;
17 extern int always_checksum;
18 extern char *partial_dir;
19 extern char *compare_dest;
20 @@ -249,6 +250,94 @@ static void generate_and_send_sums(int f
24 +static void split_names(char *fname, char **dirname, char **basename)
26 + char *slash = strrchr(fname, '/');
30 + *basename = slash+1;
38 +static unsigned int measure_name(const char *name, const char *basename,
41 + int namelen = strlen(name);
42 + int extlen = strlen(ext);
43 + unsigned int score = 0;
45 + /* Extensions must match */
46 + if (namelen <= extlen || strcmp(name + namelen - extlen, ext) != 0)
49 + /* Now score depends on similarity of prefix */
50 + for (; *name == *basename && *name; name++, basename++)
56 +static int find_fuzzy(char **fname_ptr, char *buf, STRUCT_STAT *st_ptr)
60 + char *basename, *dirname;
61 + char mangled_name[MAXPATHLEN];
62 + char bestname[MAXPATHLEN];
63 + unsigned int bestscore = 0;
66 + strlcpy(mangled_name, *fname_ptr, sizeof mangled_name);
68 + split_names(mangled_name, &dirname, &basename);
69 + if (!(d = opendir(dirname))) {
70 + rsyserr(FERROR, errno, "recv_generator opendir(%s)", dirname);
74 + /* Get final extension, eg. .gz; never full basename though. */
75 + ext = strrchr(basename + 1, '.');
77 + ext = basename + strlen(basename); /* ext = "" */
79 + while ((di = readdir(d)) != NULL) {
80 + const char *dname = d_name(di);
83 + if (dname[0] == '.' && (dname[1] == '\0'
84 + || (dname[1] == '.' && dname[2] == '\0')))
87 + score = measure_name(dname, basename, ext);
89 + rprintf(FINFO, "[%s] fuzzy score for %s = %u\n",
90 + who_am_i(), dname, score);
92 + if (score > bestscore) {
93 + strlcpy(bestname, dname, sizeof bestname);
99 + /* Found a candidate. */
100 + if (bestscore != 0) {
101 + pathjoin(buf, MAXPATHLEN, dirname, bestname);
103 + rprintf(FINFO, "[%s] fuzzy match %s->%s\n",
104 + who_am_i(), *fname_ptr, buf);
107 + return link_stat(buf, st_ptr, 0);
114 * Acts on file number @p i from @p flist, whose name is @p fname.
115 @@ -263,7 +352,7 @@ static void recv_generator(char *fname,
119 - int statret, stat_errno;
120 + int statret, stat_errno, fuzzy_file = 0;
122 char fnamecmpbuf[MAXPATHLEN];
124 @@ -448,6 +537,14 @@ static void recv_generator(char *fname,
128 + if (statret == -1 && fuzzy) {
129 + statret = find_fuzzy(&fnamecmp, fnamecmpbuf, &st);
130 + if (!S_ISREG(st.st_mode))
136 if (statret == 0 && !S_ISREG(st.st_mode)) {
137 if (delete_file(fname) != 0)
139 @@ -481,7 +578,7 @@ static void recv_generator(char *fname,
143 - if (skip_file(fname, file, &st)) {
144 + if (!fuzzy_file && skip_file(fname, file, &st)) {
146 set_perms(fname, file, &st, PERMS_REPORT);
148 --- orig/main.c 2004-07-22 00:10:43
149 +++ main.c 2004-07-22 00:32:31
150 @@ -47,6 +47,7 @@ extern int keep_dirlinks;
151 extern int preserve_hard_links;
152 extern int protocol_version;
155 extern int relative_paths;
156 extern int rsync_port;
157 extern int whole_file;
158 @@ -458,7 +459,7 @@ static int do_recv(int f_in,int f_out,st
161 int error_pipe[2], name_pipe[2];
162 - BOOL need_name_pipe = compare_dest && !dry_run;
163 + BOOL need_name_pipe = (compare_dest || fuzzy) && !dry_run;
165 if (preserve_hard_links)
166 init_hard_links(flist);
167 --- orig/options.c 2004-07-26 16:43:48
168 +++ options.c 2004-07-16 20:14:12
169 @@ -85,6 +85,7 @@ int safe_symlinks = 0;
170 int copy_unsafe_links = 0;
174 size_t bwlimit_writemax = 0;
175 int delete_after = 0;
176 int only_existing = 0;
177 @@ -279,6 +280,7 @@ void usage(enum logcode F)
178 rprintf(F," -T, --temp-dir=DIR create temporary files in directory DIR\n");
179 rprintf(F," --compare-dest=DIR also compare destination files relative to DIR\n");
180 rprintf(F," --link-dest=DIR create hardlinks to DIR for unchanged files\n");
181 + rprintf(F," --fuzzy use similar file as basis if basis doesn't exist\n");
182 rprintf(F," -P equivalent to --partial --progress\n");
183 rprintf(F," -z, --compress compress file data\n");
184 rprintf(F," -C, --cvs-exclude auto ignore files in the same way CVS does\n");
185 @@ -378,6 +380,7 @@ static struct poptOption long_options[]
186 {"temp-dir", 'T', POPT_ARG_STRING, &tmpdir, 0, 0, 0 },
187 {"compare-dest", 0, POPT_ARG_STRING, &compare_dest, 0, 0, 0 },
188 {"link-dest", 0, POPT_ARG_STRING, &compare_dest, OPT_LINK_DEST, 0, 0 },
189 + {"fuzzy", 0, POPT_ARG_NONE, &fuzzy, 0, 0, 0 },
190 /* TODO: Should this take an optional int giving the compression level? */
191 {"compress", 'z', POPT_ARG_NONE, &do_compression, 0, 0, 0 },
192 {"daemon", 0, POPT_ARG_NONE, &daemon_opt, 0, 0, 0 },
193 @@ -1039,6 +1042,9 @@ void server_options(char **args,int *arg
197 + if (fuzzy && am_sender)
198 + args[ac++] = "--fuzzy";
203 --- orig/receiver.c 2004-07-23 21:59:07
204 +++ receiver.c 2004-07-23 22:08:03
205 @@ -39,7 +39,6 @@ extern int cvs_exclude;
208 extern char *partial_dir;
209 -extern char *compare_dest;
210 extern int make_backups;
211 extern int do_progress;
212 extern char *backup_dir;
213 --- orig/rsync.yo 2004-07-28 02:26:19
214 +++ rsync.yo 2004-07-03 19:27:25
215 @@ -327,6 +327,7 @@ verb(
216 -T --temp-dir=DIR create temporary files in directory DIR
217 --compare-dest=DIR also compare received files relative to DIR
218 --link-dest=DIR create hardlinks to DIR for unchanged files
219 + --fuzzy use similar file as basis if basis is gone
220 -P equivalent to --partial --progress
221 -z, --compress compress file data
222 -C, --cvs-exclude auto ignore files in the same way CVS does