diff options
-rw-r--r-- | bin/quilt.in | 6 | ||||
-rw-r--r-- | lib/backup-files.c | 91 | ||||
-rw-r--r-- | po/de.po | 24 | ||||
-rw-r--r-- | po/fr.po | 38 | ||||
-rw-r--r-- | po/quilt.pot | 24 | ||||
-rw-r--r-- | quilt.changes | 12 | ||||
-rw-r--r-- | quilt/add.in | 2 | ||||
-rw-r--r-- | quilt/pop.in | 5 | ||||
-rw-r--r-- | quilt/remove.in | 2 | ||||
-rw-r--r-- | quilt/snapshot.in | 5 | ||||
-rwxr-xr-x | scripts/apatch.in | 11 | ||||
-rwxr-xr-x | scripts/rpatch.in | 23 | ||||
-rw-r--r-- | test/new.test | 53 | ||||
-rw-r--r-- | test/test.quiltrc | 2 |
14 files changed, 199 insertions, 99 deletions
diff --git a/bin/quilt.in b/bin/quilt.in index 858ae88..3be2f0a 100644 --- a/bin/quilt.in +++ b/bin/quilt.in @@ -7,7 +7,11 @@ # See the COPYING and AUTHORS files for more details. export TEXTDOMAIN=quilt -export QUILTRC=$HOME/.quiltrc + +if [ -z "$QUILTRC" ] +then + export QUILTRC=$HOME/.quiltrc +fi usage() { diff --git a/lib/backup-files.c b/lib/backup-files.c index 5f37ef5..fcbd2ff 100644 --- a/lib/backup-files.c +++ b/lib/backup-files.c @@ -25,6 +25,8 @@ * -B and -Z options. */ +#define _GNU_SOURCE + #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -33,14 +35,16 @@ #include <stdlib.h> #include <errno.h> #include <string.h> +#include <alloca.h> +#include <ftw.h> const char *progname; -enum { what_backup, what_restore, what_remove }; +enum { what_noop, what_backup, what_restore, what_remove }; const char *opt_prefix="", *opt_suffix="", *opt_file; -int opt_silent, opt_what=what_backup, opt_ignore_missing; -int opt_nolinks; +int opt_silent, opt_what=what_noop, opt_ignore_missing; +int opt_nolinks, opt_walk_directory; #define LINE_LENGTH 1024 @@ -48,11 +52,12 @@ int opt_nolinks; void usage(void) { - printf("Usage: %s [-B prefix] [-z suffix] [-f {filelist|-}] [-s] [-r|-x] [-L] filename ...\n" + printf("Usage: %s [-B prefix] [-z suffix] [-f {filelist|-}] [-s] [-b|-r|-x] [-L] {filename|-} ...\n" "\n" "\tCreate hard linked backup copies of a list of files\n" "\tread from standard input.\n" "\n" + "\t-b\tCreate backup\n" "\t-r\tRestore the backup\n" "\t-x\tRemove backup files and empty parent directories\n" "\t-B\tPath name prefix for backup files\n" @@ -63,10 +68,13 @@ usage(void) } void -create_parents(char *filename) +create_parents(const char *filename) { struct stat st; - char *f = strchr(filename, '/'); + char *fn = alloca(strlen(filename) + 1), *f; + + strcpy(fn, filename); + f = strchr(fn, '/'); if (f == NULL) return; @@ -74,7 +82,7 @@ create_parents(char *filename) if (stat(f, &st) != 0) { while (f != NULL) { *f = '\0'; - mkdir(filename, 0777); + mkdir(fn, 0777); *f = '/'; f = strchr(f+1, '/'); } @@ -205,26 +213,20 @@ ensure_nolinks(const char *filename) } int -process_file(char *file) +process_file(const char *file) { - char backup[LINE_LENGTH]; - - if (strlen(opt_prefix) + strlen(file) + - strlen(opt_suffix) >= sizeof(backup)) { - perror("Line buffer too small\n"); - return 1; - } + char *backup = alloca(strlen(opt_prefix) + strlen(file) + + strlen(opt_suffix) + 1); - snprintf(backup, sizeof(backup), "%s%s%s", - opt_prefix, file, opt_suffix); + sprintf(backup, "%s%s%s", opt_prefix, file, opt_suffix); if (opt_what == what_backup) { struct stat st; - int new_file = (stat(file, &st) == -1 && errno == ENOENT); + int missing_file = (stat(file, &st) == -1 && errno == ENOENT); unlink(backup); create_parents(backup); - if (new_file) { + if (missing_file) { int fd; if (!opt_silent) @@ -289,19 +291,56 @@ process_file(char *file) unlink(backup); remove_parents(backup); return 0; + } else if (opt_what == what_noop) { + struct stat st; + int missing_file = (stat(file, &st) == -1 && errno == ENOENT); + + if (!missing_file && opt_nolinks) { + if (ensure_nolinks(file)) + return 1; + } + return 0; } else return 1; } int +walk(const char *path, const struct stat *stat, int flag, struct FTW *ftw) +{ + size_t prefix_len=strlen(opt_prefix), suffix_len=strlen(opt_suffix); + size_t len = strlen(path); + char *p; + + if (flag == FTW_DNR) { + perror(path); + return 1; + } + if (!S_ISREG(stat->st_mode)) + return 0; + if (strncmp(opt_prefix, path, prefix_len)) + return 0; /* prefix does not match */ + if (len < suffix_len || strcmp(opt_suffix, path + len - suffix_len)) + return 0; /* suffix does not match */ + + p = alloca(len - prefix_len - suffix_len + 1); + memcpy(p, path + prefix_len, len - prefix_len - suffix_len); + p[len - prefix_len - suffix_len] = '\0'; + return process_file(p); +} + +int main(int argc, char *argv[]) { int opt, status=0; progname = argv[0]; - while ((opt = getopt(argc, argv, "rxB:z:f:shFL")) != -1) { + while ((opt = getopt(argc, argv, "brxB:z:f:shFL")) != -1) { switch(opt) { + case 'b': + opt_what = what_backup; + break; + case 'r': opt_what = what_restore; break; @@ -377,7 +416,17 @@ main(int argc, char *argv[]) } } for (; optind < argc; optind++) { - if ((status = process_file(argv[optind])) != 0) + if (strcmp(argv[optind], "-") == 0) { + char *dir = strdup(opt_prefix), *d = strrchr(dir, '/'); + if (d) + *(d+1) = '\0'; + else + d = "."; + status = nftw(dir, walk, 0, 0); + free(dir); + } else + status = process_file(argv[optind]); + if (status) return status; } @@ -11,15 +11,15 @@ msgstr "" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" -#: ../bin/quilt.in:15 +#: ../bin/quilt.in:19 msgid "Usage: quilt [--trace] [--quiltrc=XX] command [-h] ..." msgstr "Verwendung: quilt [--trace] [--quiltrc=XX] befehl [-h] ..." -#: ../bin/quilt.in:17 +#: ../bin/quilt.in:21 msgid "Commands are:" msgstr "Vorhandene Befehle:" -#: ../bin/quilt.in:22 +#: ../bin/quilt.in:26 msgid "" "\n" "Common options to all commands:\n" @@ -560,7 +560,7 @@ msgstr "Kein Patch entfernt" msgid "Interrupted by user" msgstr "Unterbrechung durch Benutzer" -#: ../quilt/pop.in:183 ../quilt/push.in:216 +#: ../quilt/pop.in:188 ../quilt/push.in:216 msgid "Now at patch $patch" msgstr "Jetzt in Patch $patch" @@ -883,23 +883,23 @@ msgstr "Unterbrechung durch Benutzer; Patch $patch wurde nicht angewandt." msgid "Patch file $patch_file appears to be empty" msgstr "Patch-Datei $patch_file scheint leer zu sein" -#: ../scripts/apatch.in:83 +#: ../scripts/apatch.in:80 msgid "Applying $patch" msgstr "Anwenden von $patch" -#: ../scripts/apatch.in:119 +#: ../scripts/apatch.in:116 msgid "Patch $patch appears to be empty, applied" msgstr "Patch $patch scheint leer zu sein, angewandt" -#: ../scripts/apatch.in:122 +#: ../scripts/apatch.in:119 msgid "Applied $patch (forced; needs refresh)" msgstr "Patch $patch angewandt (erzwungen, muß aufgefrischt werden (Refresh))" -#: ../scripts/apatch.in:126 +#: ../scripts/apatch.in:123 msgid "Patch $patch does not apply (enforce with -f)" msgstr "Patch $patch läßt sich nicht anwenden (erzwingen mit -f)" -#: ../scripts/apatch.in:183 ../scripts/rpatch.in:189 +#: ../scripts/apatch.in:180 ../scripts/rpatch.in:178 msgid "The topmost patch $top needs to be refreshed first." msgstr "Der oberste Patch $top muss zuerst aufgefrischt werden (Refresh)." @@ -911,10 +911,6 @@ msgstr "Verwendung: $0 [-fRq] patchname" msgid "Patch $patch does not remove cleanly (enforce with -f)." msgstr "Patch $patch kann nicht entfernt werden (erzwingen mit -f)." -#: ../scripts/rpatch.in:117 -msgid "Patch $patch appears to be empty, removed" -msgstr "Patch $patch scheint leer zu sein, entfernt" - -#: ../scripts/rpatch.in:131 +#: ../scripts/rpatch.in:122 msgid "Removing $patch" msgstr "Entferne $patch" @@ -12,15 +12,15 @@ msgstr "" "Content-Type: text/plain; charset=ISO-8859-1\n" "Content-Transfer-Encoding: 8bit\n" -#: ../bin/quilt.in:15 +#: ../bin/quilt.in:19 msgid "Usage: quilt [--trace] [--quiltrc=XX] command [-h] ..." msgstr "Usage : quilt [--trace] [--quiltrc=XX] commande [-h] ..." -#: ../bin/quilt.in:17 +#: ../bin/quilt.in:21 msgid "Commands are:" msgstr "Les commandes sont :" -#: ../bin/quilt.in:22 +#: ../bin/quilt.in:26 msgid "" "\n" "Common options to all commands:\n" @@ -78,7 +78,7 @@ msgstr "Le patch $patch n'est pas appliqué" #: ../quilt/add.in:82 ../quilt/delete.in:67 ../quilt/diff.in:168 #: ../quilt/files.in:75 ../quilt/fold.in:78 ../quilt/fork.in:64 -#: ../quilt/pop.in:181 ../quilt/push.in:179 ../quilt/push.in:213 +#: ../quilt/pop.in:181 ../quilt/push.in:179 ../quilt/push.in:214 #: ../quilt/refresh.in:107 ../quilt/remove.in:80 msgid "No patches applied" msgstr "Aucun patch n'est appliqué" @@ -565,11 +565,11 @@ msgstr "Le patch $stop_at_patch n'est pas appliqué." msgid "No patch removed" msgstr "Aucun patch retiré" -#: ../quilt/pop.in:172 ../quilt/push.in:204 +#: ../quilt/pop.in:172 ../quilt/push.in:205 msgid "Interrupted by user" msgstr "Interrompu par l'utilisateur" -#: ../quilt/pop.in:183 ../quilt/push.in:215 +#: ../quilt/pop.in:188 ../quilt/push.in:216 msgid "Now at patch $patch" msgstr "Le patch $patch est maintenant au sommet" @@ -657,7 +657,7 @@ msgstr "Le patch $stop_at_patch est introuvable dans le fichier de série" msgid "Patch $stop_at_patch is already applied." msgstr "Le patch $stop_at_patch est déjà appliqué." -#: ../quilt/push.in:183 +#: ../quilt/push.in:184 msgid "" "The topmost patch $top is not in the series file anymore;\n" "cannot determine the next patch from the series file.\n" @@ -668,7 +668,7 @@ msgstr "" "Veuillez utiliser pop -f pour le patch du sommet, et vérifier \n" "votre fichier de série." -#: ../quilt/push.in:189 +#: ../quilt/push.in:190 msgid "File series fully applied, ends at patch $top" msgstr "La série est complètement appliquée. Le dernier patch est $top." @@ -800,7 +800,8 @@ msgstr "" #: ../quilt/setup.in:27 msgid "Usage: quilt setup [-d path-prefix] [-v] {specfile|seriesfile}" -msgstr "Usage : quilt setup [-d répertoire_source] [-v] {fichier_séries|fichier_spec}" +msgstr "" +"Usage : quilt setup [-d répertoire_source] [-v] {fichier_séries|fichier_spec}" #: ../quilt/setup.in:30 msgid "" @@ -812,7 +813,8 @@ msgid "" "-v\tverbose debug output." msgstr "" "\n" -"Initialise un arbre de sources à partir d'un fichier de spécification rpm, ou d'un fichier de série quilt.\n" +"Initialise un arbre de sources à partir d'un fichier de spécification rpm, " +"ou d'un fichier de série quilt.\n" "\n" "-d\tpréfix de chemin optionel (sous-répertoire).\n" "\n" @@ -898,24 +900,24 @@ msgstr "Interrompu par l'utilisateur ; le patch $patch n'a pas été appliqué." msgid "Patch file $patch_file appears to be empty" msgstr "Le fichier de patch $patch_file semble vide" -#: ../scripts/apatch.in:83 +#: ../scripts/apatch.in:80 msgid "Applying $patch" msgstr "Application de $patch" -#: ../scripts/apatch.in:119 +#: ../scripts/apatch.in:116 msgid "Patch $patch appears to be empty, applied" msgstr "Le patch $patch semble vide. Il a été appliqué." -#: ../scripts/apatch.in:122 +#: ../scripts/apatch.in:119 msgid "Applied $patch (forced; needs refresh)" msgstr "$patch a été appliqué (forcé ; vous devriez le rafraîchir)" -#: ../scripts/apatch.in:126 +#: ../scripts/apatch.in:123 msgid "Patch $patch does not apply (enforce with -f)" msgstr "" "Le patch $patch ne s'applique pas proprement (forcez l'application avec -f)" -#: ../scripts/apatch.in:183 ../scripts/rpatch.in:189 +#: ../scripts/apatch.in:180 ../scripts/rpatch.in:178 msgid "The topmost patch $top needs to be refreshed first." msgstr "Le patch au sommet $top doit être rafraichi au préalable." @@ -927,10 +929,6 @@ msgstr "Usage: $0 [-fRq] nom_de_patch" msgid "Patch $patch does not remove cleanly (enforce with -f)." msgstr "Le patch $patch ne se retire pas proprement (forcez avec -f)" -#: ../scripts/rpatch.in:117 -msgid "Patch $patch appears to be empty, removed" -msgstr "Le patch $patch semble vide. Il a été retiré." - -#: ../scripts/rpatch.in:131 +#: ../scripts/rpatch.in:122 msgid "Removing $patch" msgstr "Retrait de $patch" diff --git a/po/quilt.pot b/po/quilt.pot index d903fe4..7473b55 100644 --- a/po/quilt.pot +++ b/po/quilt.pot @@ -1,12 +1,12 @@ -#: ../bin/quilt.in:15 +#: ../bin/quilt.in:19 msgid "Usage: quilt [--trace] [--quiltrc=XX] command [-h] ..." msgstr "" -#: ../bin/quilt.in:17 +#: ../bin/quilt.in:21 msgid "Commands are:" msgstr "" -#: ../bin/quilt.in:22 +#: ../bin/quilt.in:26 msgid "" "\n" "Common options to all commands:\n" @@ -417,7 +417,7 @@ msgstr "" msgid "Interrupted by user" msgstr "" -#: ../quilt/pop.in:183 ../quilt/push.in:216 +#: ../quilt/pop.in:188 ../quilt/push.in:216 msgid "Now at patch $patch" msgstr "" @@ -653,23 +653,23 @@ msgstr "" msgid "Patch file $patch_file appears to be empty" msgstr "" -#: ../scripts/apatch.in:83 +#: ../scripts/apatch.in:80 msgid "Applying $patch" msgstr "" -#: ../scripts/apatch.in:119 +#: ../scripts/apatch.in:116 msgid "Patch $patch appears to be empty, applied" msgstr "" -#: ../scripts/apatch.in:122 +#: ../scripts/apatch.in:119 msgid "Applied $patch (forced; needs refresh)" msgstr "" -#: ../scripts/apatch.in:126 +#: ../scripts/apatch.in:123 msgid "Patch $patch does not apply (enforce with -f)" msgstr "" -#: ../scripts/apatch.in:183 ../scripts/rpatch.in:189 +#: ../scripts/apatch.in:180 ../scripts/rpatch.in:178 msgid "The topmost patch $top needs to be refreshed first." msgstr "" @@ -681,10 +681,6 @@ msgstr "" msgid "Patch $patch does not remove cleanly (enforce with -f)." msgstr "" -#: ../scripts/rpatch.in:117 -msgid "Patch $patch appears to be empty, removed" -msgstr "" - -#: ../scripts/rpatch.in:131 +#: ../scripts/rpatch.in:122 msgid "Removing $patch" msgstr "" diff --git a/quilt.changes b/quilt.changes index 7ba2ba0..8efae38 100644 --- a/quilt.changes +++ b/quilt.changes @@ -1,4 +1,16 @@ ------------------------------------------------------------------- +Sun Jun 6 02:02:32 CEST 2004 - agruen@suse.de + +- backup-file.c: Add code to recursively search .pc directories. + Add a "no-op" mode as default, and allow to just unlink files. +- apatch/rpatch: let backup-files search .pc directories instead + of generating temporary file lists. +- rpatch/pop: unlink files of topmost patch after popping instead + of unlinking at each step. +- If QUILTRC is set in the environment, use this as the + configuration file. + +------------------------------------------------------------------- Sat Jun 5 16:12:17 CEST 2004 - agruen@suse.de - Return exit status 2 when commands go beyond the series (top diff --git a/quilt/add.in b/quilt/add.in index 55613ee..0dd0c5e 100644 --- a/quilt/add.in +++ b/quilt/add.in @@ -101,7 +101,7 @@ do continue fi - if ! @LIB@/backup-files -s -L -B $QUILT_PC/$patch/ $SUBDIR$file + if ! @LIB@/backup-files -b -s -L -B $QUILT_PC/$patch/ $SUBDIR$file then echo $"Failed to back up file $SUBDIR$file" >&2 status=1 diff --git a/quilt/pop.in b/quilt/pop.in index 2a8e62f..b80eac4 100644 --- a/quilt/pop.in +++ b/quilt/pop.in @@ -180,6 +180,11 @@ if [ -z "$patch" ] then echo $"No patches applied" else + # Ensure that the files in the topmost patch have a link count + # of one: This will automatically be the case in the usual + # situations, but we don't want to risk file corruption in weird + # corner cases such as files added to a patch but not modified. + @LIB@/backup-files -L -s -B $QUILT_PC/$patch/ - echo $"Now at patch $patch" fi ### Local Variables: diff --git a/quilt/remove.in b/quilt/remove.in index 53e4f75..1003659 100644 --- a/quilt/remove.in +++ b/quilt/remove.in @@ -101,7 +101,7 @@ do fi # Restore file from backup - if ! @LIB@/backup-files -s -B $QUILT_PC/$patch/ -r $SUBDIR$file + if ! @LIB@/backup-files -b -s -B $QUILT_PC/$patch/ -r $SUBDIR$file then echo $"Failed to remove file $SUBDIR$file from patch $patch" status=1 diff --git a/quilt/snapshot.in b/quilt/snapshot.in index 172a3df..f92e149 100644 --- a/quilt/snapshot.in +++ b/quilt/snapshot.in @@ -67,14 +67,13 @@ snap_subdir=.snap # Clean up from previous snapshot rm -rf $QUILT_PC/$snap_subdir -mkdir -p $QUILT_PC/$snap_subdir - if [ -n "$opt_remove" ] then exit 0 fi # Save current working state +mkdir -p $QUILT_PC/$snap_subdir for patch in $(applied_patches); do files_in_patch $patch done \ @@ -85,7 +84,7 @@ done \ } { print } ' \ -| @LIB@/backup-files -s -L -f - -B "$QUILT_PC/$snap_subdir/" +| @LIB@/backup-files -b -s -L -f - -B "$QUILT_PC/$snap_subdir/" ### Local Variables: ### mode: shell-script diff --git a/scripts/apatch.in b/scripts/apatch.in index 94c74b4..38235cc 100755 --- a/scripts/apatch.in +++ b/scripts/apatch.in @@ -62,17 +62,14 @@ apply_patch() rollback_patch() { - local patch=$1 pc_file=$(gen_tempfile) + local patch=$1 - # FIXME backup_files should scan the directory hierarchy itself. - files_in_patch $patch > $pc_file - @LIB@/backup-files $silent_unless_verbose \ - -f $pc_file -B $QUILT_PC/$patch/ -r if [ -z "$opt_leave_rejects" ] then - @SED@ -e 's/$/\.rej/' $pc_file | xargs rm -f + files_in_patch | @SED@ -e 's/$/\.rej/' | xargs rm -f fi - rm -f $pc_file + + @LIB@/backup-files $silent_unless_verbose -r -B $QUILT_PC/$patch/ - } apatch() diff --git a/scripts/rpatch.in b/scripts/rpatch.in index 9b5d6e7..bbe988f 100755 --- a/scripts/rpatch.in +++ b/scripts/rpatch.in @@ -49,7 +49,7 @@ files_may_have_changed() # and report any pending changes. check_for_pending_changes() { - local patch=$1 pc_file=$2 + local patch=$1 local patch_file=$(patch_file_name $patch) local patch_args=$(patch_args $patch) local workdir=$(gen_tempfile -d quilt) status=0 @@ -90,10 +90,10 @@ check_for_pending_changes() fi local remains=$(gen_tempfile) - while read file + for file in $(files_in_patch $patch) do diff_file $file $workdir/$file $file >> $remains - done < $pc_file + done if [ -s $remains ] then @@ -108,35 +108,24 @@ check_for_pending_changes() rpatch() { - local patch=$1 pc_file=$(gen_tempfile) status=0 - - # FIXME backup-files should scan the directory tree itself. - files_in_patch $patch > $pc_file - if ! [ -s $pc_file ] - then - echo $"Patch $patch appears to be empty, removed" - remove_from_db $patch - return 0 - fi + local patch=$1 status=0 trap "" SIGINT if [ -z "$opt_force" ] && \ ( [ -n "$opt_remove" ] || files_may_have_changed $patch ) then - check_for_pending_changes $patch $pc_file || status=1 + check_for_pending_changes $patch || status=1 fi if [ $status -eq 0 ] then echo $"Removing $patch" rm -f "$QUILT_PC/$patch/.timestamp" - @LIB@/backup-files $silent -r -L -f $pc_file \ - -B $QUILT_PC/$patch/ + @LIB@/backup-files $silent -r -B $QUILT_PC/$patch/ - status=$? remove_from_db $patch rm -f $QUILT_PC/$patch~refresh fi - rm -f $pc_file trap - SIGINT return $status } diff --git a/test/new.test b/test/new.test new file mode 100644 index 0000000..dfa8f64 --- /dev/null +++ b/test/new.test @@ -0,0 +1,53 @@ + $ mkdir -p d/patches + $ cd d + + $ echo reject > f + $ echo p.diff > patches/series + $ cat > patches/p.diff + < --- d.orig/f + < +++ d/f + < @@ -1 +1 @@ + < -old + < +new + < --- d.orig/g + < +++ d/g + < @@ -0,0 +1 @@ + < +added + + + $ quilt push + > Applying p.diff + > patching file f + > Hunk #1 FAILED at 1. + > 1 out of 1 hunk FAILED -- rejects in file f + > patching file g + > Patch p.diff does not apply (enforce with -f) + + $ quilt push -f + > Applying p.diff + > patching file f + > Hunk #1 FAILED at 1. + > 1 out of 1 hunk FAILED -- saving rejects to file f.rej + > patching file g + > Applied p.diff (forced; needs refresh) + + $ echo new > f + $ quilt refresh + > Refreshed patch p.diff + $ cat patches/p.diff | sed -e "s/\\t.*//" + > Index: d/f + > =================================================================== + > --- d.orig/f + > +++ d/f + > @@ -1 +1 @@ + > -reject + > +new + > Index: d/g + > =================================================================== + > --- d.orig/g + > +++ d/g + > @@ -0,0 +1 @@ + > +added + + $ cd .. + $ rm -rf d diff --git a/test/test.quiltrc b/test/test.quiltrc new file mode 100644 index 0000000..468812d --- /dev/null +++ b/test/test.quiltrc @@ -0,0 +1,2 @@ +# Define this to generate diffs without timestamps. +QUILT_NO_DIFF_TIMESTAMPS=yes |