quilt-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Quilt-dev] [RFC][PATCH] quilt commit command


From: Josh Boyer
Subject: [Quilt-dev] [RFC][PATCH] quilt commit command
Date: Fri, 13 May 2005 19:52:50 -0500

Hi,

The patch below is an example of adding a quilt commit command.  This
command basically something similar to a 'quilt pop', but without
actually removing the applied patch from the modified files.  It also
removes the patch name from the series file and cleans up the backup
files in the .pc directory.  It should leave the actual patch file in
the patches directory however, which is handy for those "oops, I screwed
up" moments.

Often times I find myself using quilt on a project that uses a CVS, SVN,
$SCM tree to manage multiple changes until I'm ready to actually commit
them to the repository.  When I'm ready to do a $SCM checkin, I do:

quilt refresh patch-name.patch
quilt pop patch-name.patch
patch -p1 < patches/patch-name.patch
$SCM ci

By adding a commit command, users can skip the manual steps and simply
do:

quilt commit patch-name.patch
$SCM ci

It also has the benefit of cleaning up the .pc directory for them.

I have some other thoughts on how it could work (such as adding a
"committed-patches" file, etc) but I thought I would test the waters
first.  Would such a command be accepted for quilt?

josh

Makefile.in     |    2 
 quilt/commit.in |  293 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 294 insertions(+), 1 deletion(-)

Index: quilt/quilt/commit.in
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ quilt/quilt/commit.in       2005-05-13 19:39:00.734636928 -0500
@@ -0,0 +1,293 @@
+#! @BASH@
+
+#  This script is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License version 2 as
+#  published by the Free Software Foundation.
+#
+#  See the COPYING and AUTHORS files for more details.
+
+# Read in library functions
+if [ "$(type -t patch_file_name)" != function ]
+then
+       if ! [ -r @SCRIPTS@/patchfns ]
+       then
+               echo "Cannot read library @SCRIPTS@/patchfns" >&2
+               exit 1
+       fi
+       . @SCRIPTS@/patchfns
+fi
+
+usage()
+{
+       printf $"Usage: quilt commit [-afqv] [num|patch]\n"
+       if [ x$1 = x-h ]
+       then
+               printf $"
+Commit patch(es) from the stack of applied patches.  Without options,
+the topmost patch is committed.  When a number is specified, commit the
+specified number of patches.  When a patch name is specified, commit
+patches until the specified patch end up on top of the stack.  Patch
+names may include the patches/ prefix, which means that filename
+completion can be used.
+
+-a     Commit all applied patches.
+
+-f     Force commit.
+
+-q     Quiet operation.
+
+-v     Verbose operation.
+"
+               exit 0
+       else
+               exit 1
+       fi
+}
+
+list_patches()
+{
+       local n=0 patch
+       applied_patches \
+       | tac \
+       | if [ -n "$opt_all" ]
+       then
+               cat
+       else
+               while read patch
+               do
+                       if [ -n "$number" ]
+                       then
+                               if [ $n -eq $number ]
+                               then
+                                       break
+                               fi
+                               n=$[$n+1]
+                       fi
+                       if [ $patch = "$stop_at_patch" ]
+                       then
+                               break
+                       fi
+                       echo $patch
+               done
+       fi
+}
+
+files_may_have_changed()
+{
+       local patch=$1 file
+       local patch_file=$(patch_file_name $patch)
+
+       if [ $? -ne 0 -o ! -e "$patch_file" \
+            -o ! -e "$QUILT_PC/$patch/.timestamp" \
+            -o "$QUILT_PC/$patch/.timestamp" -ot "$patch_file" ]
+       then
+               return 0
+       fi
+
+       local apply_ts=$(date -r "$QUILT_PC/$patch/.timestamp" '+%s') ts
+       for file in $(files_in_patch $patch)
+       do
+               ts=$(date -r $file '+%s' 2> /dev/null)
+               [ -z "$ts" ] && return 0
+               [ "$ts" -gt $apply_ts ] && return 0
+       done
+       return 1
+}
+
+# Check if all changes have been folded back into the patch (quilt refresh),
+# and report any pending changes.
+check_for_pending_changes()
+{
+       local patch=$1
+       local patch_file=$(patch_file_name $patch)
+       local workdir=$(gen_tempfile -d quilt) status=0
+
+       if [ -d $QUILT_PC/$patch ]
+       then
+               if ! rmdir $workdir ||  # note that this is racey...
+                  ! cp -rl $QUILT_PC/$patch $workdir
+               then
+                       printf $"Failed to copy files to temporary directory\n" 
>&2
+                       rm -rf $workdir
+                       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 '{}' ';'
+
+       fi
+
+       if [ -s $patch_file ]
+       then
+               if ! cat_file $patch_file \
+                    | @PATCH@ -d $workdir $QUILT_PATCH_OPTS \
+                              $(patch_args $patch) \
+                              --no-backup-if-mismatch -E \
+                              >/dev/null 2>/dev/null
+               then
+                       if ! [ -e $QUILT_PC/$patch ]
+                       then
+                               printf $"Failed to patch temporary files\n" >&2
+                               rm -rf $workdir
+                               return 1
+                       fi
+               fi
+       fi
+
+       local file failed
+       for file2 in $(files_in_patch $patch)
+       do
+               file=$workdir/$file2
+               [ -e $file  ] || file=/dev/null
+               [ -e $file2 ] || file2=/dev/null
+               @DIFF@ -q $file $file2 > /dev/null || failed=1
+       done
+
+       if [ -n "$failed" ]
+       then
+               printf $"Patch %s does not commit cleanly (refresh it or 
enforce with -f)\n" \
+                      "$(print_patch $patch)" >&2
+               status=1
+       fi
+       rm -rf $workdir
+
+       return $status
+}
+
+remove_patch()
+{
+       local patch=$1 status=0
+
+       trap "status=1" SIGINT
+       if [ -z "$opt_force" ] && \
+          ( [ -n "$opt_remove" ] || files_may_have_changed $patch )
+       then
+               check_for_pending_changes $patch || status=1
+       fi
+
+       if [ $status -eq 0 ]
+       then
+               printf $"Committing patch %s\n" "$(print_patch $patch)"
+               rm -f "$QUILT_PC/$patch/.timestamp"
+               @LIB@/backup-files $silent -x -B $QUILT_PC/$patch/ -
+               status=$?
+               remove_from_db $patch
+               remove_from_series $patch
+               rm -f $QUILT_PC/$patch~refresh
+       fi
+       trap - SIGINT
+       return $status
+}
+
+options=`getopt -o fqvah -- "$@"`
+
+if [ $? -ne 0 ]
+then
+        usage
+fi
+
+eval set -- "$options"
+
+while true
+do
+        case "$1" in
+    -f)
+                opt_force=1
+               unset opt_remove
+               shift ;;
+    -q)
+                opt_quiet=1
+               shift ;;
+    -v)
+                opt_verbose=1
+               shift ;;
+       -a)
+               opt_all=1
+               shift ;;
+       -h)
+               usage -h ;;
+    --)
+                shift
+               break ;;
+        esac
+done
+
+if [ $# -gt 1 -o \( -n "$opt_all" -a $# -ne 0 \) ]
+then
+        usage
+fi
+
+if [ $# -eq 1 ]
+then
+       if is_numeric $1
+       then
+               number=$1
+       else
+               if ! stop_at_patch=$(find_patch $1)
+               then
+                       printf $"Patch %s is not in series\n" "$1" >&2
+                       exit 1
+               fi
+       fi
+else
+       [ -n "$opt_all" ] || number=1
+fi
+
+[ -n "$opt_quiet" ] && silent=-s
+[ -z "$opt_verbose" ] && silent_unless_verbose=-s
+
+if [ -n "$stop_at_patch" ]
+then
+       if ! is_applied $stop_at_patch
+       then
+               printf $"Patch %s is not applied\n" "$(print_patch 
$stop_at_patch)" >&2
+               exit 1
+       fi
+fi
+
+top=$(top_patch)
+if [ -n "$top" -a -e $QUILT_PC/$top~refresh -a -z "$opt_force" ]
+then
+       printf $"Patch %s needs to be refreshed first.\n" \
+              "$(print_patch $top)" >&2
+       exit 1
+fi
+
+if ! patches=$(list_patches) 2>&1
+then
+       exit 1
+elif [ -z "$patches" ]
+then
+        printf $"No patch removed\n" >&2
+       exit 2
+fi
+
+for patch in $patches
+do
+       if ! remove_patch $patch
+       then
+               exit 1
+       fi
+       [ -z "$opt_quiet" ] && echo
+done
+
+patch="$(top_patch)"
+if [ -z "$patch" ]
+then
+       printf $"No patches applied\n"
+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/ -
+       printf $"Now at patch %s\n" "$(print_patch $patch)"
+fi
+### Local Variables:
+### mode: shell-script
+### End:
+# vim:filetype=sh
Index: quilt/Makefile.in
===================================================================
--- quilt.orig/Makefile.in      2005-05-13 19:38:56.787237024 -0500
+++ quilt/Makefile.in   2005-05-13 19:39:00.734636928 -0500
@@ -56,7 +56,7 @@ BIN :=                $(BIN_IN)
 SRC +=         $(BIN_SRC:%=bin/%)
 DIRT +=                $(BIN_IN:%=bin/%)
 
-QUILT_IN :=    add applied delete diff edit files fold fork graph grep \
+QUILT_IN :=    add applied commit delete diff edit files fold fork graph grep \
                import mail new next patches pop previous push refresh remove \
                series setup snapshot top unapplied upgrade
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]