Index: quilt/quilt/diff.in =================================================================== --- quilt.orig/quilt/diff.in +++ quilt/quilt/diff.in @@ -80,7 +80,8 @@ included. } colorize() { - if [ -n "$opt_color" ]; then + if [ -n "$opt_color" ] + then sed -e ' s/^\(Index:\|---\|+++\|\*\*\*\) .*/'$color_diff_hdr'&'$color_clear'/ t ; s/^+.*/'$color_diff_add'&'$color_clear'/ @@ -304,42 +305,9 @@ fi if [ -n "$opt_relative" ] then - patch_file=$(patch_file_name $last_patch) - patch_args=$(patch_args $last_patch) workdir=$(gen_tempfile -d $PWD/quilt) - - if [ ${#files[@]} -gt 0 ] \ - && ! ( cd $QUILT_PC/$last_patch && - cp -l --parents "${files[@]}" $workdir/ ) - then - printf $"Failed to copy files to temporary directory\n" >&2 - die 1 - fi - # Now we may have some zero-size files that have no permissions - # (which represent files that the patch creates). Those may have - # been created in the meantime, but patch would refuse to touch - # them: We must remove them here. - find $workdir -type f -size 0 -exec rm -f '{}' ';' - - if [ -s $patch_file ] - then - if ! cat_file $patch_file \ - | patch -d $workdir $QUILT_PATCH_OPTS $patch_args \ - --no-backup-if-mismatch -Ef \ - >/dev/null 2>/dev/null - then - # Generating a relative diff for a subset of files in - # the patch will fail. Also, if a patch was force - # applied, we know that it won't apply cleanly. In - # all other cases, print a warning. - - if [ ! -e $QUILT_PC/$last_patch~refresh -a \ - ${#opt_files[@]} -eq 0 ] - then - printf $"Failed to patch temporary files\n" >&2 - fi - fi - fi + apply_patch_temporarily "$workdir" "$last_patch" "${files[@]}" \ + || die 1 fi for file in "${files[@]}" Index: quilt/quilt/fork.in =================================================================== --- quilt.orig/quilt/fork.in +++ quilt/quilt/fork.in @@ -72,11 +72,7 @@ if [ $# -eq 1 ] then new_patch="$1" else - base=$(echo "$top_patch" \ - | sed -r -e 's:(\.gz|\.bz2)$::' -e 's:(\.diff?|\.patch)$::') - num=$(echo "$base" | sed -nre 's:.*-([0-9]+)$:\1:'p) - [ -n "$num" ] || num=1 - new_patch="${base%-$num}-$((num+1))${top_patch#$base}" + new_patch="$(next_filename "$top_patch")" fi new_patch=${new_patch#$QUILT_PATCHES/} Index: quilt/quilt/refresh.in =================================================================== --- quilt.orig/quilt/refresh.in +++ quilt/quilt/refresh.in @@ -19,7 +19,7 @@ fi usage() { - printf $"Usage: quilt refresh [-p n|-p ab] [-u|-U num|-c|-C num] [-f] [--no-timestamps] [--no-index] [--diffstat] [--sort] [--backup] [--strip-trailing-whitespace] [patch]\n" + printf $"Usage: quilt refresh [-p n|-p ab] [-u|-U num|-c|-C num] [-z[new_name]] [-f] [--no-timestamps] [--no-index] [--diffstat] [--sort] [--backup] [--strip-trailing-whitespace] [patch]\n" if [ x$1 = x-h ] then @@ -47,6 +47,11 @@ patch. a context diff (-c, -C) with num lines of context. The number of context lines defaults to 3. +-z[new_name] + Create a new patch containing the changes instead of refreshing the + topmost patch. If no new name is specified, \`-2' is added to the + original patch name, etc. (See the fork command.) + --no-timestamps Do not include file timestamps in patch headers. @@ -77,14 +82,14 @@ die() { local status=$1 [ -n "$tmp_patch" ] && rm -f $tmp_patch - [ -n "$tmp_header" ] && rm -f $tmp_header [ -n "$tmp_result" ] && rm -f $tmp_result + [ -n "$workdir" ] && rm -rf $workdir exit $status } -options=`getopt -o p:uU:cC:fh --long no-timestamps,diffstat,backup,sort \ - --long no-index \ - --long strip-trailing-whitespace -- "$@"` +options=`getopt -o p:uU:cC:fz::h --long no-timestamps,diffstat,backup,sort \ + --long no-index \ + --long strip-trailing-whitespace -- "$@"` if [ $? -ne 0 ] then @@ -109,6 +114,10 @@ do -U|-C) opt_format="$1 $2" shift 2 ;; + -z) + opt_fork=1 + opt_new_name=$2 + shift 2 ;; -h) usage -h ;; --no-timestamps) @@ -144,6 +153,34 @@ QUILT_DIFF_OPTS="$QUILT_DIFF_OPTS $opt_f patch=$(find_applied_patch "$1") || exit 1 +if [ -z "$opt_sort" ] +then + files=( $(files_in_patch_ordered $patch) ) +else + files=( $(files_in_patch $patch | sort) ) +fi + +if [ -n "$opt_fork" -a $# -ne 0 ] +then + printf $"Can only refresh the topmost patch with -z currently\n" >&2 + exit 1 +fi + +if [ -n "$opt_fork" ]; then + old_patch=$patch + old_patch_args=$(patch_args "$old_patch") + if [ -n "$opt_new_name" ] + then + patch=$opt_new_name + else + patch=$(next_filename "$patch") + fi + if [ -e "$(patch_file_name "patch")" ]; then + printf $"Patch %s exists already\n" "$(print_patch $patch)" >&2 + exit 1 + fi +fi + if [ -z "$opt_strip_level" ] then opt_strip_level=$(patch_strip_level $patch) @@ -163,27 +200,30 @@ esac trap "die 1" SIGTERM -tmp_patch=$(gen_tempfile) - -if [ -z "$opt_sort" ] -then - files=( $(files_in_patch_ordered $patch) ) -else - files=( $(files_in_patch $patch | sort) ) +if [ -n "$opt_fork" ]; then + workdir=$(gen_tempfile -d $PWD/quilt) + apply_patch_temporarily "$workdir" "$old_patch" || exit 1 fi +tmp_patch=$(gen_tempfile) + for file in "${files[@]}" do - old_file=$(backup_file_name $patch $file) - next_patch=$(next_patch_for_file $patch $file) - if [ -z "$next_patch" ] - then + if [ -n "$opt_fork" ]; then + old_file=$workdir/$file new_file=$file else - new_file=$(backup_file_name $next_patch $file) - files_were_shadowed=1 + old_file=$(backup_file_name $patch $file) + next_patch=$(next_patch_for_file $patch $file) + if [ -z "$next_patch" ] + then + new_file=$file + else + new_file=$(backup_file_name $next_patch $file) + files_were_shadowed=1 + fi fi - if ! diff_file $file $old_file $new_file >> $tmp_patch + if ! diff_file $file $old_file $new_file then printf $"Diff failed, aborting\n" >&2 die 1 @@ -199,7 +239,7 @@ do then printf $"Cannot use --strip-trailing-whitespace on a patch that has shadowed files.\n" >&2 fi -done +done >> $tmp_patch if ! [ -s $tmp_patch ] then @@ -227,25 +267,17 @@ patch_file=$(patch_file_name $patch) trap "" SIGINT -if ! tmp_header=$(gen_tempfile) -then - die 1 -fi - -mkdir -p $(dirname $patch_file) - -if ! cat_file $patch_file | patch_header > $tmp_header -then - die 1 -fi - tmp_result=$(gen_tempfile) || die 1 +prev_patch_file=$patch_file +[ -e "$prev_patch_file" ] || prev_patch_file=/dev/null + if [ -n "$opt_diffstat" ] then diffstat="$(diffstat $QUILT_DIFFSTAT_OPTS \ -p$num_strip_level $tmp_patch)" || die 1 - awk ' + cat_file "$prev_patch_file" | patch_header \ + | awk ' function print_diffstat(arr, i) { split(diffstat, arr, "\n") for (i=1; i in arr; i++) @@ -271,13 +303,16 @@ then } } ' diffstat="$diffstat" \ - $tmp_header > $tmp_result + > $tmp_result else - cat $tmp_header > $tmp_result + cat_file "$prev_patch_file" | patch_header \ + > $tmp_result fi cat $tmp_patch >> $tmp_result +mkdir -p $(dirname $patch_file) + if [ -e $patch_file ] && \ diff -q $patch_file $tmp_result > /dev/null then @@ -286,8 +321,30 @@ elif ( [ -z "$QUILT_BACKUP" -o ! -e $pat mv $patch_file $patch_file~ ) && \ cat_to_new_file $patch_file < $tmp_result then + if [ -n "$opt_fork" ] + then + if ! insert_in_series "$patch" "$old_patch_args" + then + printf $"Failed to insert patch %s into file series\n" \ + "$(print_patch $patch)" >&2 + rm -f "$patch_file" + exit 1 + fi + if ! rm -rf "$QUILT_PC/$patch" || \ + ! mv "$workdir" "$QUILT_PC/$patch" || \ + ! echo "$patch" >> $QUILT_PC/applied-patches + then + printf $"Failed to create patch %s\n" \ + "$(print_patch $patch)" >&2 + exit 1 + fi + printf $"Fork of patch %s created as %s\n" \ + "$(print_patch $old_patch)" \ + "$(print_patch $patch)" + else + printf $"Refreshed patch %s\n" "$(print_patch $patch)" + fi touch $QUILT_PC/$patch/.timestamp - printf $"Refreshed patch %s\n" "$(print_patch $patch)" else die 1 fi Index: quilt/quilt/scripts/patchfns.in =================================================================== --- quilt.orig/quilt/scripts/patchfns.in +++ quilt/quilt/scripts/patchfns.in @@ -838,6 +838,65 @@ first_modified_by() return 1 } +apply_patch_temporarily() +{ + local workdir=$1 patch=$2 patch_file patch_args files + + patch_file=$(patch_file_name "$patch") + patch_args=$(patch_args "$patch") + + shift 2 + if [ $# -gt 0 ] + then + files=( "$@" ) + else + files=( $(files_in_patch "$patch") ) + fi + + if [ ${#files[@]} -gt 0 ] \ + && ! ( cd $QUILT_PC/$patch && + cp -l --parents "${files[@]}" $workdir/ ) + then + printf $"Failed to copy files to temporary directory\n" >&2 + return 1 + fi + # Now we may have some zero-size files that have no permissions + # (which represent files that the patch creates). Those may have + # been created in the meantime, but patch would refuse to touch + # them: We must remove them here. + find $workdir -type f -size 0 -exec rm -f '{}' ';' + + if [ -s $patch_file ] + then + if ! cat_file $patch_file \ + | patch -d $workdir $QUILT_PATCH_OPTS $patch_args \ + --no-backup-if-mismatch -Ef \ + >/dev/null 2>/dev/null + then + # Generating a relative diff for a subset of files in + # the patch will fail. Also, if a patch was force + # applied, we know that it won't apply cleanly. In + # all other cases, print a warning. + + if [ ! -e $QUILT_PC/$patch~refresh -a $# -eq 0 ] + then + printf $"Failed to patch temporary files\n" >&2 + return 1 + fi + fi + fi +} + +next_filename() +{ + local patch=$1 base num + base=$(echo "$patch" \ + | sed -r -e 's:(\.gz|\.bz2)$::' -e 's:(\.diff?|\.patch)$::') + num=$(echo "$base" | sed -nre 's:.*-([0-9]+)$:\1:'p) + [ -n "$num" ] || num=1 + echo "${base%-$num}-$((num+1))${patch#$base}" +} + create_db() { if ! [ -e $QUILT_PC ] then Index: quilt/test/refresh-z.test =================================================================== --- /dev/null +++ quilt/test/refresh-z.test @@ -0,0 +1,29 @@ + $ rm -rf d + $ mkdir -p d/patches + $ cd d + + $ quilt new test.diff + > Patch patches/test.diff is now on top + + $ quilt add foo + > File foo added to patch patches/test.diff + + $ echo foo > foo + $ quilt refresh + > Refreshed patch patches/test.diff + + $ echo bar >> foo + $ quilt refresh -z + > Fork of patch patches/test.diff created as patches/test-2.diff + + $ echo baz >> foo + $ quilt refresh -zbaz.diff + > Fork of patch patches/test-2.diff created as patches/baz.diff + + $ quilt series + > patches/test.diff + > patches/test-2.diff + > patches/baz.diff + + $ cd .. + $ rm -rf d