Skip to content

Commit e2fc650

Browse files
author
Junio C Hamano
committed
Merge branch 'jc/merge' into next
* jc/merge: git-merge knows some strategies want to skip trivial merges generate-cmdlist: style cleanups. Add missing semicolon to sed command. unpack_delta_entry(): reduce memory footprint. git.el: Added a function to diff against the other heads in a merge. git.el: Get the default user name and email from the repository config. git.el: More robust handling of subprocess errors when returning strings.
2 parents 1656313 + 6ea2334 commit e2fc650

File tree

4 files changed

+90
-56
lines changed

4 files changed

+90
-56
lines changed

contrib/emacs/git.el

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@
5959

6060
(defcustom git-committer-name nil
6161
"User name to use for commits.
62-
The default is to fall back to `add-log-full-name' and then `user-full-name'."
62+
The default is to fall back to the repository config, then to `add-log-full-name' and then to `user-full-name'."
6363
:group 'git
6464
:type '(choice (const :tag "Default" nil)
6565
(string :tag "Name")))
6666

6767
(defcustom git-committer-email nil
6868
"Email address to use for commits.
69-
The default is to fall back to `add-log-mailing-address' and then `user-mail-address'."
69+
The default is to fall back to the git repository config, then to `add-log-mailing-address' and then to `user-mail-address'."
7070
:group 'git
7171
:type '(choice (const :tag "Default" nil)
7272
(string :tag "Email")))
@@ -148,6 +148,12 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add
148148
(append (git-get-env-strings env) (list "git") args))
149149
(apply #'call-process "git" nil buffer nil args)))
150150

151+
(defun git-call-process-env-string (env &rest args)
152+
"Wrapper for call-process that sets environment strings, and returns the process output as a string."
153+
(with-temp-buffer
154+
(and (eq 0 (apply #' git-call-process-env t env args))
155+
(buffer-string))))
156+
151157
(defun git-run-process-region (buffer start end program args)
152158
"Run a git process with a buffer region as input."
153159
(let ((output-buffer (current-buffer))
@@ -189,13 +195,15 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add
189195

190196
(defun git-get-string-sha1 (string)
191197
"Read a SHA1 from the specified string."
192-
(let ((pos (string-match "[0-9a-f]\\{40\\}" string)))
193-
(and pos (substring string pos (match-end 0)))))
198+
(and string
199+
(string-match "[0-9a-f]\\{40\\}" string)
200+
(match-string 0 string)))
194201

195202
(defun git-get-committer-name ()
196203
"Return the name to use as GIT_COMMITTER_NAME."
197204
; copied from log-edit
198205
(or git-committer-name
206+
(git-repo-config "user.name")
199207
(and (boundp 'add-log-full-name) add-log-full-name)
200208
(and (fboundp 'user-full-name) (user-full-name))
201209
(and (boundp 'user-full-name) user-full-name)))
@@ -204,6 +212,7 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add
204212
"Return the email address to use as GIT_COMMITTER_EMAIL."
205213
; copied from log-edit
206214
(or git-committer-email
215+
(git-repo-config "user.email")
207216
(and (boundp 'add-log-mailing-address) add-log-mailing-address)
208217
(and (fboundp 'user-mail-address) (user-mail-address))
209218
(and (boundp 'user-mail-address) user-mail-address)))
@@ -259,18 +268,17 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add
259268
(defun git-rev-parse (rev)
260269
"Parse a revision name and return its SHA1."
261270
(git-get-string-sha1
262-
(with-output-to-string
263-
(with-current-buffer standard-output
264-
(git-call-process-env t nil "rev-parse" rev)))))
271+
(git-call-process-env-string nil "rev-parse" rev)))
272+
273+
(defun git-repo-config (key)
274+
"Retrieve the value associated to KEY in the git repository config file."
275+
(let ((str (git-call-process-env-string nil "repo-config" key)))
276+
(and str (car (split-string str "\n")))))
265277

266278
(defun git-symbolic-ref (ref)
267279
"Wrapper for the git-symbolic-ref command."
268-
(car
269-
(split-string
270-
(with-output-to-string
271-
(with-current-buffer standard-output
272-
(git-call-process-env t nil "symbolic-ref" ref)))
273-
"\n")))
280+
(let ((str (git-call-process-env-string nil "symbolic-ref" ref)))
281+
(and str (car (split-string str "\n")))))
274282

275283
(defun git-update-ref (ref val &optional oldval)
276284
"Update a reference by calling git-update-ref."
@@ -285,11 +293,7 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add
285293
(defun git-write-tree (&optional index-file)
286294
"Call git-write-tree and return the resulting tree SHA1 as a string."
287295
(git-get-string-sha1
288-
(with-output-to-string
289-
(with-current-buffer standard-output
290-
(git-call-process-env t
291-
(if index-file `(("GIT_INDEX_FILE" . ,index-file)) nil)
292-
"write-tree")))))
296+
(git-call-process-env-string (and index-file `(("GIT_INDEX_FILE" . ,index-file))) "write-tree")))
293297

294298
(defun git-commit-tree (buffer tree head)
295299
"Call git-commit-tree with buffer as input and return the resulting commit SHA1."
@@ -763,6 +767,16 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add
763767
(git-setup-diff-buffer
764768
(apply #'git-run-command-buffer "*git-diff*" "diff-index" "-p" "-M" "HEAD" "--" (git-get-filenames files)))))
765769

770+
(defun git-diff-file-merge-head (arg)
771+
"Diff the marked file(s) against the first merge head (or the nth one with a numeric prefix)."
772+
(interactive "p")
773+
(let ((files (git-marked-files))
774+
(merge-heads (git-get-merge-heads)))
775+
(unless merge-heads (error "No merge in progress"))
776+
(git-setup-diff-buffer
777+
(apply #'git-run-command-buffer "*git-diff*" "diff-index" "-p" "-M"
778+
(or (nth (1- arg) merge-heads) "HEAD") "--" (git-get-filenames files)))))
779+
766780
(defun git-diff-unmerged-file (stage)
767781
"Diff the marked unmerged file(s) against the specified stage."
768782
(let ((files (git-marked-files)))
@@ -955,6 +969,7 @@ The default is to fall back to `add-log-mailing-address' and then `user-mail-add
955969
(define-key diff-map "=" 'git-diff-file)
956970
(define-key diff-map "e" 'git-diff-file-idiff)
957971
(define-key diff-map "E" 'git-find-file-imerge)
972+
(define-key diff-map "h" 'git-diff-file-merge-head)
958973
(define-key diff-map "m" 'git-diff-file-mine)
959974
(define-key diff-map "o" 'git-diff-file-other)
960975
(setq git-status-mode-map map)))

generate-cmdlist.sh

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,12 @@ whatchanged
4141
EOF
4242
while read cmd
4343
do
44-
sed -n "/NAME/,/git-$cmd/H;
45-
\$ {x; s/.*git-$cmd - \\(.*\\)/ {\"$cmd\", \"\1\"},/; p}" \
46-
"Documentation/git-$cmd.txt"
44+
sed -n '
45+
/NAME/,/git-'"$cmd"'/H
46+
${
47+
x
48+
s/.*git-'"$cmd"' - \(.*\)/ {"'"$cmd"'", "\1"},/
49+
p
50+
}' "Documentation/git-$cmd.txt"
4751
done
4852
echo "};"

git-merge.sh

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@ LF='
1111
'
1212

1313
all_strategies='recursive octopus resolve stupid ours'
14-
default_strategies='recursive'
14+
default_twohead_strategies='recursive'
15+
default_octopus_strategies='octopus'
16+
no_trivial_merge_strategies='ours'
1517
use_strategies=
18+
19+
index_merge=t
1620
if test "@@NO_PYTHON@@"; then
1721
all_strategies='resolve octopus stupid ours'
18-
default_strategies='resolve'
22+
default_twohead_strategies='resolve'
1923
fi
2024

2125
dropsave() {
@@ -90,15 +94,15 @@ do
9094
shift
9195
done
9296

93-
test "$#" -le 2 && usage ;# we need at least two heads.
94-
9597
merge_msg="$1"
9698
shift
9799
head_arg="$1"
98100
head=$(git-rev-parse --verify "$1"^0) || usage
99101
shift
100102

101103
# All the rest are remote heads
104+
test "$#" = 0 && usage ;# we need at least one remote head.
105+
102106
remoteheads=
103107
for remote
104108
do
@@ -108,6 +112,27 @@ do
108112
done
109113
set x $remoteheads ; shift
110114

115+
case "$use_strategies" in
116+
'')
117+
case "$#" in
118+
1)
119+
use_strategies="$default_twohead_strategies" ;;
120+
*)
121+
use_strategies="$default_octopus_strategies" ;;
122+
esac
123+
;;
124+
esac
125+
126+
for s in $use_strategies
127+
do
128+
case " $s " in
129+
*" $no_trivial_merge_strategies "*)
130+
index_merge=f
131+
break
132+
;;
133+
esac
134+
done
135+
111136
case "$#" in
112137
1)
113138
common=$(git-merge-base --all $head "$@")
@@ -118,18 +143,21 @@ case "$#" in
118143
esac
119144
echo "$head" >"$GIT_DIR/ORIG_HEAD"
120145

121-
case "$#,$common,$no_commit" in
122-
*,'',*)
146+
case "$index_merge,$#,$common,$no_commit" in
147+
f,*)
148+
# We've been told not to try anything clever. Skip to real merge.
149+
;;
150+
?,*,'',*)
123151
# No common ancestors found. We need a real merge.
124152
;;
125-
1,"$1",*)
153+
?,1,"$1",*)
126154
# If head can reach all the merge then we are up to date.
127-
# but first the most common case of merging one remote
155+
# but first the most common case of merging one remote.
128156
echo "Already up-to-date."
129157
dropsave
130158
exit 0
131159
;;
132-
1,"$head",*)
160+
?,1,"$head",*)
133161
# Again the most common case of merging one remote.
134162
echo "Updating from $head to $1"
135163
git-update-index --refresh 2>/dev/null
@@ -139,11 +167,11 @@ case "$#,$common,$no_commit" in
139167
dropsave
140168
exit 0
141169
;;
142-
1,?*"$LF"?*,*)
170+
?,1,?*"$LF"?*,*)
143171
# We are not doing octopus and not fast forward. Need a
144172
# real merge.
145173
;;
146-
1,*,)
174+
?,1,*,)
147175
# We are not doing octopus, not fast forward, and have only
148176
# one common. See if it is really trivial.
149177
git var GIT_COMMITTER_IDENT >/dev/null || exit
@@ -188,17 +216,6 @@ esac
188216
# We are going to make a new commit.
189217
git var GIT_COMMITTER_IDENT >/dev/null || exit
190218

191-
case "$use_strategies" in
192-
'')
193-
case "$#" in
194-
1)
195-
use_strategies="$default_strategies" ;;
196-
*)
197-
use_strategies=octopus ;;
198-
esac
199-
;;
200-
esac
201-
202219
# At this point, we need a real merge. No matter what strategy
203220
# we use, it would operate on the index, possibly affecting the
204221
# working tree, and when resolved cleanly, have the desired tree
@@ -270,11 +287,7 @@ done
270287
# auto resolved the merge cleanly.
271288
if test '' != "$result_tree"
272289
then
273-
parents="-p $head"
274-
for remote
275-
do
276-
parents="$parents -p $remote"
277-
done
290+
parents=$(git-show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
278291
result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents) || exit
279292
finish "$result_commit" "Merge $result_commit, made by $wt_strategy."
280293
dropsave

sha1_file.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,16 @@ static void *unpack_delta_entry(unsigned char *base_sha1,
973973

974974
if (left < 20)
975975
die("truncated pack file");
976+
977+
/* The base entry _must_ be in the same pack */
978+
if (!find_pack_entry_one(base_sha1, &base_ent, p))
979+
die("failed to find delta-pack base object %s",
980+
sha1_to_hex(base_sha1));
981+
base = unpack_entry_gently(&base_ent, type, &base_size);
982+
if (!base)
983+
die("failed to read delta-pack base object %s",
984+
sha1_to_hex(base_sha1));
985+
976986
data = base_sha1 + 20;
977987
data_size = left - 20;
978988
delta_data = xmalloc(delta_size);
@@ -990,14 +1000,6 @@ static void *unpack_delta_entry(unsigned char *base_sha1,
9901000
if ((st != Z_STREAM_END) || stream.total_out != delta_size)
9911001
die("delta data unpack failed");
9921002

993-
/* The base entry _must_ be in the same pack */
994-
if (!find_pack_entry_one(base_sha1, &base_ent, p))
995-
die("failed to find delta-pack base object %s",
996-
sha1_to_hex(base_sha1));
997-
base = unpack_entry_gently(&base_ent, type, &base_size);
998-
if (!base)
999-
die("failed to read delta-pack base object %s",
1000-
sha1_to_hex(base_sha1));
10011003
result = patch_delta(base, base_size,
10021004
delta_data, delta_size,
10031005
&result_size);

0 commit comments

Comments
 (0)