diff options
author | Andreas Gruenbacher <agruen@suse.de> | 2010-04-29 14:19:13 +0200 |
---|---|---|
committer | Andreas Gruenbacher <agruen@suse.de> | 2010-05-02 11:44:03 +0200 |
commit | b68294e3e1177bcf98d6d23f90ef3e6b5576af2a (patch) | |
tree | 2f6fcca8d1579115dd4467689f66f7563511a7c4 | |
parent | f9db7450fa2788377c4567b5d0565b0ddfc1015c (diff) | |
download | patch-b68294e3e1177bcf98d6d23f90ef3e6b5576af2a.tar.gz |
git diffs: Support file mode changes
* src/patch.c (main): When a git diff includes a file mode change,
change to the new mode.
* src/util.c (set_file_attributes): Add a mode parameter.
* tests/file-modes: New test case.
* tests/Makefile.am (TESTS): Add test case.
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | src/patch.c | 13 | ||||
-rw-r--r-- | src/util.c | 10 | ||||
-rw-r--r-- | src/util.h | 2 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/file-modes | 84 |
6 files changed, 107 insertions, 9 deletions
@@ -1,5 +1,11 @@ 2009-04-29 Andreas Gruenbacher <agruen@suse.de> + * src/patch.c (main): When a git diff includes a file mode change, + change to the new mode. + * src/util.c (set_file_attributes): Add a mode parameter. + * tests/file-modes: New test case. + * tests/Makefile.am (TESTS): Add test case. + * src/patch.c (main): Support git symlink diffs. * tests/symlinks: Add git symlink diff test cases. diff --git a/src/patch.c b/src/patch.c index 741ad79..07913bb 100644 --- a/src/patch.c +++ b/src/patch.c @@ -406,12 +406,17 @@ main (int argc, char **argv) if (! dry_run) { + mode_t old_mode = pch_mode (reverse); + mode_t new_mode = pch_mode (! reverse); + bool set_mode = new_mode && old_mode != new_mode; + /* Avoid replacing files when nothing has changed. */ - if (failed < hunk || diff_type == ED_DIFF) + if (failed < hunk || diff_type == ED_DIFF || set_mode) { enum file_attributes attr = FA_IDS | FA_MODE; struct timespec new_time = pch_timestamp (! reverse); - mode_t mode = file_type | (instat.st_mode & S_IRWXUGO); + mode_t mode = file_type | + ((new_mode ? new_mode : instat.st_mode) & S_IRWXUGO); move_file (TMPOUTNAME, &TMPOUTNAME_needs_removal, &outst, outname, mode, backup); @@ -437,9 +442,9 @@ main (int argc, char **argv) } if (! inerrno) - set_file_attributes (outname, attr, &instat, &new_time); + set_file_attributes (outname, attr, &instat, mode, &new_time); } - else + else if (backup) create_backup (outname, 0, 0, true); } } @@ -124,7 +124,7 @@ contains_slash (const char *s) void set_file_attributes (char const *to, enum file_attributes attr, - struct stat *st, struct timespec *new_time) + struct stat *st, mode_t mode, struct timespec *new_time) { if (attr & FA_TIMES) { @@ -171,10 +171,12 @@ set_file_attributes (char const *to, enum file_attributes attr, } if (attr & FA_MODE) { + if (! mode) + mode = st->st_mode; #ifdef HAVE_LCHMOD - if (lchmod (to, st->st_mode)) + if (lchmod (to, mode)) #else - if (! S_ISLNK (st->st_mode) && chmod (to, st->st_mode) != 0) + if (! S_ISLNK (mode) && chmod (to, mode) != 0) #endif pfatal ("Failed to set the permissions of %s %s", S_ISLNK (st->st_mode) ? "symbolic link" : "file", @@ -188,7 +190,7 @@ create_backup_copy (char const *from, char const *to, struct stat *st, bool to_dir_known_to_exist) { copy_file (from, to, 0, 0, st->st_mode, to_dir_known_to_exist); - set_file_attributes (to, FA_TIMES | FA_IDS | FA_MODE, st, NULL); + set_file_attributes (to, FA_TIMES | FA_IDS | FA_MODE, st, 0, NULL); } void @@ -71,7 +71,7 @@ enum file_attributes { }; void set_file_attributes (char const *, enum file_attributes, struct stat *, - struct timespec *); + mode_t, struct timespec *); static inline char const * skip_spaces (char const *str) diff --git a/tests/Makefile.am b/tests/Makefile.am index 3df2e74..af30156 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -23,6 +23,7 @@ TESTS = \ create-delete \ crlf-handling \ dash-o-append \ + file-modes \ filename-choice \ git-binary-diff \ global-reject-files \ diff --git a/tests/file-modes b/tests/file-modes new file mode 100644 index 0000000..9da184a --- /dev/null +++ b/tests/file-modes @@ -0,0 +1,84 @@ +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# Copying and distribution of this file, with or without modification, +# in any medium, are permitted without royalty provided the copyright +# notice and this notice are preserved. + +# Test if git diffs can change file modes + +. $srcdir/test-lib.sh + +require_cat +require_diff +use_local_patch +use_tmpdir + +# ============================================================== + +cat > f.diff <<EOF +diff --git a/f b/f +old mode 100644 +new mode 100600 +--- a/f ++++ a/f +@@ -1 +1 @@ +-old ++new + +diff --git a/g b/g +old mode 100644 +new mode 100600 +--- a/g ++++ a/g +@@ -1 +1 @@ +-old ++new + +EOF + +echo old > f +echo old > g +chmod 644 f g + +check 'patch -p1 < f.diff' <<EOF +patching file f +patching file g +EOF + +check 'ls -l f g | sed "s,\(..........\).*,\1,"' <<EOF +-rw------- +-rw------- +EOF + +check 'patch -p1 -R < f.diff' <<EOF +patching file f +patching file g +EOF + +check 'ls -l f g | sed "s,\(..........\).*,\1,"' <<EOF +-rw-r--r-- +-rw-r--r-- +EOF + +cat > g.diff <<EOF +diff --git a/f b/f +old mode 100644 +new mode 100600 + +diff --git a/g b/g +old mode 100644 +new mode 100600 + +EOF + +chmod 600 f +chmod 644 g +check 'patch -p1 < g.diff || echo "Status: $?"' <<EOF +patching file f +patching file g +EOF + +check 'ls -l f g | sed "s,\(..........\).*,\1,"' <<EOF +-rw------- +-rw------- +EOF |