From 9de83169d34825d617b7fe92b95c966d9910848d Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 19 Mar 2006 10:05:22 +0100 Subject: git.el: More robust handling of subprocess errors when returning strings. Make sure that functions that call a git process and return a string always return nil when the subprocess failed. Signed-off-by: Alexandre Julliard Signed-off-by: Junio C Hamano --- contrib/emacs/git.el | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index 5135e361be..cf650da3e5 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -148,6 +148,12 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add (append (git-get-env-strings env) (list "git") args)) (apply #'call-process "git" nil buffer nil args))) +(defun git-call-process-env-string (env &rest args) + "Wrapper for call-process that sets environment strings, and returns the process output as a string." + (with-temp-buffer + (and (eq 0 (apply #' git-call-process-env t env args)) + (buffer-string)))) + (defun git-run-process-region (buffer start end program args) "Run a git process with a buffer region as input." (let ((output-buffer (current-buffer)) @@ -189,8 +195,9 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add (defun git-get-string-sha1 (string) "Read a SHA1 from the specified string." - (let ((pos (string-match "[0-9a-f]\\{40\\}" string))) - (and pos (substring string pos (match-end 0))))) + (and string + (string-match "[0-9a-f]\\{40\\}" string) + (match-string 0 string))) (defun git-get-committer-name () "Return the name to use as GIT_COMMITTER_NAME." @@ -259,18 +266,12 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add (defun git-rev-parse (rev) "Parse a revision name and return its SHA1." (git-get-string-sha1 - (with-output-to-string - (with-current-buffer standard-output - (git-call-process-env t nil "rev-parse" rev))))) + (git-call-process-env-string nil "rev-parse" rev))) (defun git-symbolic-ref (ref) "Wrapper for the git-symbolic-ref command." - (car - (split-string - (with-output-to-string - (with-current-buffer standard-output - (git-call-process-env t nil "symbolic-ref" ref))) - "\n"))) + (let ((str (git-call-process-env-string nil "symbolic-ref" ref))) + (and str (car (split-string str "\n"))))) (defun git-update-ref (ref val &optional oldval) "Update a reference by calling git-update-ref." @@ -285,11 +286,7 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add (defun git-write-tree (&optional index-file) "Call git-write-tree and return the resulting tree SHA1 as a string." (git-get-string-sha1 - (with-output-to-string - (with-current-buffer standard-output - (git-call-process-env t - (if index-file `(("GIT_INDEX_FILE" . ,index-file)) nil) - "write-tree"))))) + (git-call-process-env-string (and index-file `(("GIT_INDEX_FILE" . ,index-file))) "write-tree"))) (defun git-commit-tree (buffer tree head) "Call git-commit-tree with buffer as input and return the resulting commit SHA1." -- cgit v1.2.3 From 75a8180d4b6939aca03b2c6320f128469abd5879 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 19 Mar 2006 10:05:48 +0100 Subject: git.el: Get the default user name and email from the repository config. If user name or email are not set explicitly, get them from the user.name and user.email configuration values before falling back to the Emacs defaults. Signed-off-by: Alexandre Julliard Signed-off-by: Junio C Hamano --- contrib/emacs/git.el | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index cf650da3e5..5496a1bb5e 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -59,14 +59,14 @@ (defcustom git-committer-name nil "User name to use for commits. -The default is to fall back to `add-log-full-name' and then `user-full-name'." +The default is to fall back to the repository config, then to `add-log-full-name' and then to `user-full-name'." :group 'git :type '(choice (const :tag "Default" nil) (string :tag "Name"))) (defcustom git-committer-email nil "Email address to use for commits. -The default is to fall back to `add-log-mailing-address' and then `user-mail-address'." +The default is to fall back to the git repository config, then to `add-log-mailing-address' and then to `user-mail-address'." :group 'git :type '(choice (const :tag "Default" nil) (string :tag "Email"))) @@ -203,6 +203,7 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add "Return the name to use as GIT_COMMITTER_NAME." ; copied from log-edit (or git-committer-name + (git-repo-config "user.name") (and (boundp 'add-log-full-name) add-log-full-name) (and (fboundp 'user-full-name) (user-full-name)) (and (boundp 'user-full-name) user-full-name))) @@ -211,6 +212,7 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add "Return the email address to use as GIT_COMMITTER_EMAIL." ; copied from log-edit (or git-committer-email + (git-repo-config "user.email") (and (boundp 'add-log-mailing-address) add-log-mailing-address) (and (fboundp 'user-mail-address) (user-mail-address)) (and (boundp 'user-mail-address) user-mail-address))) @@ -268,6 +270,11 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add (git-get-string-sha1 (git-call-process-env-string nil "rev-parse" rev))) +(defun git-repo-config (key) + "Retrieve the value associated to KEY in the git repository config file." + (let ((str (git-call-process-env-string nil "repo-config" key))) + (and str (car (split-string str "\n"))))) + (defun git-symbolic-ref (ref) "Wrapper for the git-symbolic-ref command." (let ((str (git-call-process-env-string nil "symbolic-ref" ref))) -- cgit v1.2.3 From 2b1c0ef2e5d103efacb535f32fb142114490dc33 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Sun, 19 Mar 2006 10:06:10 +0100 Subject: git.el: Added a function to diff against the other heads in a merge. git-diff-file-merge-head generates a diff against the first merge head, or with a prefix argument against the nth head. Bound to `d h' by default. Signed-off-by: Alexandre Julliard Signed-off-by: Junio C Hamano --- contrib/emacs/git.el | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index 5496a1bb5e..ebd00ef9c4 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -767,6 +767,16 @@ The default is to fall back to the git repository config, then to `add-log-maili (git-setup-diff-buffer (apply #'git-run-command-buffer "*git-diff*" "diff-index" "-p" "-M" "HEAD" "--" (git-get-filenames files))))) +(defun git-diff-file-merge-head (arg) + "Diff the marked file(s) against the first merge head (or the nth one with a numeric prefix)." + (interactive "p") + (let ((files (git-marked-files)) + (merge-heads (git-get-merge-heads))) + (unless merge-heads (error "No merge in progress")) + (git-setup-diff-buffer + (apply #'git-run-command-buffer "*git-diff*" "diff-index" "-p" "-M" + (or (nth (1- arg) merge-heads) "HEAD") "--" (git-get-filenames files))))) + (defun git-diff-unmerged-file (stage) "Diff the marked unmerged file(s) against the specified stage." (let ((files (git-marked-files))) @@ -959,6 +969,7 @@ The default is to fall back to the git repository config, then to `add-log-maili (define-key diff-map "=" 'git-diff-file) (define-key diff-map "e" 'git-diff-file-idiff) (define-key diff-map "E" 'git-find-file-imerge) + (define-key diff-map "h" 'git-diff-file-merge-head) (define-key diff-map "m" 'git-diff-file-mine) (define-key diff-map "o" 'git-diff-file-other) (setq git-status-mode-map map))) -- cgit v1.2.3 From 67686d95044e56475669ff1306448e41a794a865 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 19 Mar 2006 13:43:42 -0800 Subject: unpack_delta_entry(): reduce memory footprint. Currently we unpack the delta data from the pack and then unpack the base object to apply that delta data to it. When getting an object that is deeply deltified, we can reduce memory footprint by unpacking the base object first and then unpacking the delta data, because we will need to keep at most one delta data in memory that way. Signed-off-by: Junio C Hamano --- sha1_file.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sha1_file.c b/sha1_file.c index a80d849f15..58edec0bb6 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -973,6 +973,16 @@ static void *unpack_delta_entry(unsigned char *base_sha1, if (left < 20) die("truncated pack file"); + + /* The base entry _must_ be in the same pack */ + if (!find_pack_entry_one(base_sha1, &base_ent, p)) + die("failed to find delta-pack base object %s", + sha1_to_hex(base_sha1)); + base = unpack_entry_gently(&base_ent, type, &base_size); + if (!base) + die("failed to read delta-pack base object %s", + sha1_to_hex(base_sha1)); + data = base_sha1 + 20; data_size = left - 20; delta_data = xmalloc(delta_size); @@ -990,14 +1000,6 @@ static void *unpack_delta_entry(unsigned char *base_sha1, if ((st != Z_STREAM_END) || stream.total_out != delta_size) die("delta data unpack failed"); - /* The base entry _must_ be in the same pack */ - if (!find_pack_entry_one(base_sha1, &base_ent, p)) - die("failed to find delta-pack base object %s", - sha1_to_hex(base_sha1)); - base = unpack_entry_gently(&base_ent, type, &base_size); - if (!base) - die("failed to read delta-pack base object %s", - sha1_to_hex(base_sha1)); result = patch_delta(base, base_size, delta_data, delta_size, &result_size); -- cgit v1.2.3 From ad52e7708dca3ea5c295867e844d9228d1a96f36 Mon Sep 17 00:00:00 2001 From: Shawn Pearce Date: Sun, 19 Mar 2006 19:18:08 -0500 Subject: Add missing semicolon to sed command. generate-cmdlist.sh is giving errors messages from sed on Mac OS 10.4 due to a missing semicolon. Signed-off-by: Junio C Hamano --- generate-cmdlist.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh index 6ee85d5a53..76ba49c88c 100755 --- a/generate-cmdlist.sh +++ b/generate-cmdlist.sh @@ -42,7 +42,7 @@ EOF while read cmd do sed -n "/NAME/,/git-$cmd/H; - \$ {x; s/.*git-$cmd - \\(.*\\)/ {\"$cmd\", \"\1\"},/; p}" \ + \$ {x; s/.*git-$cmd - \\(.*\\)/ {\"$cmd\", \"\1\"},/; p;}" \ "Documentation/git-$cmd.txt" done echo "};" -- cgit v1.2.3 From fd662dd500cded4b04b1154dc77cc989a5ddc5b8 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 19 Mar 2006 23:54:45 -0800 Subject: generate-cmdlist: style cleanups. Instead of giving multiple commands concatenated with semicolon to sed, write them on separate lines. Signed-off-by: Junio C Hamano --- generate-cmdlist.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh index 76ba49c88c..6c59dbd68f 100755 --- a/generate-cmdlist.sh +++ b/generate-cmdlist.sh @@ -41,8 +41,12 @@ whatchanged EOF while read cmd do - sed -n "/NAME/,/git-$cmd/H; - \$ {x; s/.*git-$cmd - \\(.*\\)/ {\"$cmd\", \"\1\"},/; p;}" \ - "Documentation/git-$cmd.txt" + sed -n ' + /NAME/,/git-'"$cmd"'/H + ${ + x + s/.*git-'"$cmd"' - \(.*\)/ {"'"$cmd"'", "\1"},/ + p + }' "Documentation/git-$cmd.txt" done echo "};" -- cgit v1.2.3 From 6ea23343ce2962a5c76ed62a29fd17cb30954de2 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 18 Mar 2006 14:50:53 -0800 Subject: git-merge knows some strategies want to skip trivial merges Most notably "ours". Also this makes sure we do not record duplicated parents on the parent list of the resulting commit. This is based on Mark Wooding's work, but does not change the UI nor introduce new flags. Signed-off-by: Junio C Hamano --- git-merge.sh | 67 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/git-merge.sh b/git-merge.sh index cc0952a97d..78ab422e4e 100755 --- a/git-merge.sh +++ b/git-merge.sh @@ -11,11 +11,15 @@ LF=' ' all_strategies='recursive octopus resolve stupid ours' -default_strategies='recursive' +default_twohead_strategies='recursive' +default_octopus_strategies='octopus' +no_trivial_merge_strategies='ours' use_strategies= + +index_merge=t if test "@@NO_PYTHON@@"; then all_strategies='resolve octopus stupid ours' - default_strategies='resolve' + default_twohead_strategies='resolve' fi dropsave() { @@ -90,8 +94,6 @@ do shift done -test "$#" -le 2 && usage ;# we need at least two heads. - merge_msg="$1" shift head_arg="$1" @@ -99,6 +101,8 @@ head=$(git-rev-parse --verify "$1"^0) || usage shift # All the rest are remote heads +test "$#" = 0 && usage ;# we need at least one remote head. + remoteheads= for remote do @@ -108,6 +112,27 @@ do done set x $remoteheads ; shift +case "$use_strategies" in +'') + case "$#" in + 1) + use_strategies="$default_twohead_strategies" ;; + *) + use_strategies="$default_octopus_strategies" ;; + esac + ;; +esac + +for s in $use_strategies +do + case " $s " in + *" $no_trivial_merge_strategies "*) + index_merge=f + break + ;; + esac +done + case "$#" in 1) common=$(git-merge-base --all $head "$@") @@ -118,18 +143,21 @@ case "$#" in esac echo "$head" >"$GIT_DIR/ORIG_HEAD" -case "$#,$common,$no_commit" in -*,'',*) +case "$index_merge,$#,$common,$no_commit" in +f,*) + # We've been told not to try anything clever. Skip to real merge. + ;; +?,*,'',*) # No common ancestors found. We need a real merge. ;; -1,"$1",*) +?,1,"$1",*) # If head can reach all the merge then we are up to date. - # but first the most common case of merging one remote + # but first the most common case of merging one remote. echo "Already up-to-date." dropsave exit 0 ;; -1,"$head",*) +?,1,"$head",*) # Again the most common case of merging one remote. echo "Updating from $head to $1" git-update-index --refresh 2>/dev/null @@ -139,11 +167,11 @@ case "$#,$common,$no_commit" in dropsave exit 0 ;; -1,?*"$LF"?*,*) +?,1,?*"$LF"?*,*) # We are not doing octopus and not fast forward. Need a # real merge. ;; -1,*,) +?,1,*,) # We are not doing octopus, not fast forward, and have only # one common. See if it is really trivial. git var GIT_COMMITTER_IDENT >/dev/null || exit @@ -188,17 +216,6 @@ esac # We are going to make a new commit. git var GIT_COMMITTER_IDENT >/dev/null || exit -case "$use_strategies" in -'') - case "$#" in - 1) - use_strategies="$default_strategies" ;; - *) - use_strategies=octopus ;; - esac - ;; -esac - # At this point, we need a real merge. No matter what strategy # we use, it would operate on the index, possibly affecting the # working tree, and when resolved cleanly, have the desired tree @@ -270,11 +287,7 @@ done # auto resolved the merge cleanly. if test '' != "$result_tree" then - parents="-p $head" - for remote - do - parents="$parents -p $remote" - done + parents=$(git-show-branch --independent "$head" "$@" | sed -e 's/^/-p /') result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents) || exit finish "$result_commit" "Merge $result_commit, made by $wt_strategy." dropsave -- cgit v1.2.3