summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/Makefile1
-rw-r--r--Documentation/asciidoc.conf2
-rw-r--r--Documentation/git-ls-files.txt4
-rw-r--r--Documentation/git.txt7
-rw-r--r--Documentation/repository-layout.txt8
-rw-r--r--Documentation/urls.txt17
-rw-r--r--Makefile8
-rw-r--r--blob.c6
-rw-r--r--builtin-diff.c6
-rw-r--r--builtin-fmt-merge-msg.c18
-rw-r--r--builtin-grep.c4
-rw-r--r--builtin-prune.c259
-rw-r--r--builtin-rev-list.c6
-rw-r--r--builtin-show-branch.c9
-rw-r--r--builtin.h2
-rw-r--r--commit.c299
-rw-r--r--contrib/emacs/git.el17
-rw-r--r--daemon.c77
-rw-r--r--describe.c2
-rw-r--r--diff.c176
-rw-r--r--exec_cmd.c19
-rw-r--r--fetch-pack.c10
-rw-r--r--fetch.c8
-rw-r--r--fsck-objects.c10
-rwxr-xr-xgit-commit.sh32
-rwxr-xr-xgit-fetch.sh2
-rwxr-xr-xgit-prune.sh44
-rwxr-xr-xgit-repack.sh4
-rwxr-xr-xgit-revert.sh2
-rwxr-xr-xgit-svn.perl2
-rw-r--r--git.c39
-rwxr-xr-xgitweb/gitweb.cgi84
-rw-r--r--gitweb/gitweb.css9
-rw-r--r--http-push.c12
-rw-r--r--merge-file.c166
-rw-r--r--merge-tree.c207
-rw-r--r--name-rev.c8
-rw-r--r--object.c7
-rw-r--r--object.h23
-rw-r--r--pack.h15
-rw-r--r--quote.c17
-rw-r--r--quote.h1
-rw-r--r--revision.c12
-rw-r--r--send-pack.c4
-rw-r--r--server-info.c2
-rw-r--r--sha1_file.c26
-rw-r--r--sha1_name.c12
-rwxr-xr-xt/t4013-diff-various.sh5
-rw-r--r--t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master2
-rw-r--r--t/t4013/diff.diff-tree_--cc_--patch-with-stat_master2
-rw-r--r--t/t4013/diff.diff-tree_--cc_--stat_--summary_master2
-rw-r--r--t/t4013/diff.diff-tree_--cc_--stat_master2
-rw-r--r--t/t4013/diff.diff-tree_--cc_master2
-rw-r--r--t/t4013/diff.diff-tree_-c_--abbrev_master2
-rw-r--r--t/t4013/diff.diff-tree_-c_--stat_--summary_master2
-rw-r--r--t/t4013/diff.diff-tree_-c_--stat_master2
-rw-r--r--t/t4013/diff.diff-tree_-c_master2
-rw-r--r--t/t4013/diff.diff-tree_-p_-m_master4
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..master17
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..master^16
-rw-r--r--t/t4013/diff.format-patch_--attach_--stdout_initial..side1
-rw-r--r--t/t4013/diff.format-patch_--stdout_initial..master8
-rw-r--r--t/t4013/diff.format-patch_--stdout_initial..master^7
-rw-r--r--t/t4013/diff.format-patch_--stdout_initial..side1
-rw-r--r--t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_10
-rw-r--r--t/t4013/diff.log_--patch-with-stat_master10
-rw-r--r--t/t4013/diff.log_--patch-with-stat_master_--_dir_10
-rw-r--r--t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master10
-rw-r--r--t/t4013/diff.log_--root_--patch-with-stat_--summary_master10
-rw-r--r--t/t4013/diff.log_--root_--patch-with-stat_master10
-rw-r--r--t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master10
-rw-r--r--t/t4013/diff.log_--root_-p_master10
-rw-r--r--t/t4013/diff.log_--root_master10
-rw-r--r--t/t4013/diff.log_-SF_-p_master2
-rw-r--r--t/t4013/diff.log_-SF_master2
-rw-r--r--t/t4013/diff.log_-p_master10
-rw-r--r--t/t4013/diff.log_master10
-rw-r--r--t/t4013/diff.show_master4
-rw-r--r--t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_6
-rw-r--r--t/t4013/diff.whatchanged_--patch-with-stat_master6
-rw-r--r--t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_6
-rw-r--r--t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master10
-rw-r--r--t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master6
-rw-r--r--t/t4013/diff.whatchanged_--root_--patch-with-stat_master6
-rw-r--r--t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master10
-rw-r--r--t/t4013/diff.whatchanged_--root_-p_master6
-rw-r--r--t/t4013/diff.whatchanged_--root_master6
-rw-r--r--t/t4013/diff.whatchanged_-SF_-p_master2
-rw-r--r--t/t4013/diff.whatchanged_-SF_master2
-rw-r--r--t/t4013/diff.whatchanged_-p_master6
-rw-r--r--t/t4013/diff.whatchanged_master6
-rwxr-xr-xt/t6010-merge-base.sh45
-rwxr-xr-xt/test-lib.sh1
-rw-r--r--tag.c8
-rw-r--r--tree.c12
-rw-r--r--upload-pack.c8
-rw-r--r--xdiff/xdiff.h1
-rw-r--r--xdiff/xemit.c18
98 files changed, 1446 insertions, 625 deletions
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 2b0efe7921..6dbe45b506 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -46,6 +46,7 @@ all: html man
html: $(DOC_HTML)
+$(DOC_HTML) $(DOC_MAN1) $(DOC_MAN7): asciidoc.conf
man: man1 man7
man1: $(DOC_MAN1)
diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
index 7ce71510de..8196d787ab 100644
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -9,6 +9,8 @@
[attributes]
caret=^
+startsb=[
+endsb=]
ifdef::backend-docbook[]
[gitlink-inlinemacro]
diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 4d8a2ad2d7..8520b97111 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -207,7 +207,7 @@ An exclude pattern is of the following format:
An example:
--------------------------------------------------------------
- $ cat .git/ignore
+ $ cat .git/info/exclude
# ignore objects and archives, anywhere in the tree.
*.[oa]
$ cat Documentation/.gitignore
@@ -217,7 +217,7 @@ An example:
!foo.html
$ git-ls-files --ignored \
--exclude='Documentation/*.[0-9]' \
- --exclude-from=.git/ignore \
+ --exclude-from=.git/info/exclude \
--exclude-per-directory=.gitignore
--------------------------------------------------------------
diff --git a/Documentation/git.txt b/Documentation/git.txt
index d00cc3ea52..ce3058182f 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -615,6 +615,13 @@ git Diffs
gitlink:git-diff-files[1];
gitlink:git-diff-tree[1]
+other
+~~~~~
+'GIT_TRACE'::
+ If this variable is set git will print `trace:` messages on
+ stderr telling about alias expansion, built-in command
+ execution and external command execution.
+
Discussion[[Discussion]]
------------------------
include::README[]
diff --git a/Documentation/repository-layout.txt b/Documentation/repository-layout.txt
index b52dfdc308..275d18bb54 100644
--- a/Documentation/repository-layout.txt
+++ b/Documentation/repository-layout.txt
@@ -120,9 +120,11 @@ info/grafts::
info/exclude::
This file, by convention among Porcelains, stores the
- exclude pattern list. `git status` looks at it, but
- otherwise it is not looked at by any of the core git
- commands.
+ exclude pattern list. `.gitignore` is the per-directory
+ ignore file. `git status`, `git add`, `git rm` and `git
+ clean` look at it but the core git commands do not look
+ at it. See also: gitlink:git-ls-files[1] `--exclude-from`
+ and `--exclude-per-directory`.
remotes::
Stores shorthands to be used to give URL and default
diff --git a/Documentation/urls.txt b/Documentation/urls.txt
index 9abec806d9..26ecba53fb 100644
--- a/Documentation/urls.txt
+++ b/Documentation/urls.txt
@@ -10,20 +10,21 @@ to name the remote repository:
- https://host.xz/path/to/repo.git/
- git://host.xz/path/to/repo.git/
- git://host.xz/~user/path/to/repo.git/
-- ssh://[user@]host.xz/path/to/repo.git/
-- ssh://[user@]host.xz/~user/path/to/repo.git/
-- ssh://[user@]host.xz/~/path/to/repo.git
+- ssh://{startsb}user@{endsb}host.xz/path/to/repo.git/
+- ssh://{startsb}user@{endsb}host.xz/~user/path/to/repo.git/
+- ssh://{startsb}user@{endsb}host.xz/~/path/to/repo.git
===============================================================
-SSH Is the default transport protocol and also supports an
-scp-like syntax. Both syntaxes support username expansion,
+SSH is the default transport protocol. You can optionally specify
+which user to log-in as, and an alternate, scp-like syntax is also
+supported. Both syntaxes support username expansion,
as does the native git protocol. The following three are
identical to the last three above, respectively:
===============================================================
-- host.xz:/path/to/repo.git/
-- host.xz:~user/path/to/repo.git/
-- host.xz:path/to/repo.git
+- {startsb}user@{endsb}host.xz:/path/to/repo.git/
+- {startsb}user@{endsb}host.xz:~user/path/to/repo.git/
+- {startsb}user@{endsb}host.xz:path/to/repo.git
===============================================================
To sync with a local directory, use:
diff --git a/Makefile b/Makefile
index e75fb133aa..01fb9cfdbd 100644
--- a/Makefile
+++ b/Makefile
@@ -124,7 +124,7 @@ SCRIPT_SH = \
git-fetch.sh \
git-ls-remote.sh \
git-merge-one-file.sh git-parse-remote.sh \
- git-prune.sh git-pull.sh git-rebase.sh \
+ git-pull.sh git-rebase.sh \
git-repack.sh git-request-pull.sh git-reset.sh \
git-resolve.sh git-revert.sh git-sh-setup.sh \
git-tag.sh git-verify-tag.sh \
@@ -178,7 +178,7 @@ BUILT_INS = git-log$X git-whatchanged$X git-show$X git-update-ref$X \
git-read-tree$X git-commit-tree$X git-write-tree$X \
git-apply$X git-show-branch$X git-diff-files$X git-update-index$X \
git-diff-index$X git-diff-stages$X git-diff-tree$X git-cat-file$X \
- git-fmt-merge-msg$X
+ git-fmt-merge-msg$X git-prune$X
# what 'all' will build and 'install' will install, in gitexecdir
ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)
@@ -222,7 +222,7 @@ LIB_OBJS = \
server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \
- alloc.o $(DIFF_OBJS)
+ alloc.o merge-file.o $(DIFF_OBJS)
BUILTIN_OBJS = \
builtin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \
@@ -234,7 +234,7 @@ BUILTIN_OBJS = \
builtin-apply.o builtin-show-branch.o builtin-diff-files.o \
builtin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \
builtin-cat-file.o builtin-mailsplit.o builtin-stripspace.o \
- builtin-update-ref.o builtin-fmt-merge-msg.o
+ builtin-update-ref.o builtin-fmt-merge-msg.o builtin-prune.o
GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
LIBS = $(GITLIBS) -lz
diff --git a/blob.c b/blob.c
index 496f270043..d1af2e62f1 100644
--- a/blob.c
+++ b/blob.c
@@ -10,12 +10,12 @@ struct blob *lookup_blob(const unsigned char *sha1)
if (!obj) {
struct blob *ret = alloc_blob_node();
created_object(sha1, &ret->object);
- ret->object.type = TYPE_BLOB;
+ ret->object.type = OBJ_BLOB;
return ret;
}
if (!obj->type)
- obj->type = TYPE_BLOB;
- if (obj->type != TYPE_BLOB) {
+ obj->type = OBJ_BLOB;
+ if (obj->type != OBJ_BLOB) {
error("Object %s is a %s, not a blob",
sha1_to_hex(sha1), typename(obj->type));
return NULL;
diff --git a/builtin-diff.c b/builtin-diff.c
index ae901dd25e..cb38f44561 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -285,9 +285,9 @@ int cmd_diff(int argc, const char **argv, char **envp)
obj = deref_tag(obj, NULL, 0);
if (!obj)
die("invalid object '%s' given.", name);
- if (obj->type == TYPE_COMMIT)
+ if (obj->type == OBJ_COMMIT)
obj = &((struct commit *)obj)->tree->object;
- if (obj->type == TYPE_TREE) {
+ if (obj->type == OBJ_TREE) {
if (ARRAY_SIZE(ent) <= ents)
die("more than %d trees given: '%s'",
(int) ARRAY_SIZE(ent), name);
@@ -297,7 +297,7 @@ int cmd_diff(int argc, const char **argv, char **envp)
ents++;
continue;
}
- if (obj->type == TYPE_BLOB) {
+ if (obj->type == OBJ_BLOB) {
if (2 <= blobs)
die("more than two blobs given: '%s'", name);
memcpy(blob[blobs].sha1, obj->sha1, 20);
diff --git a/builtin-fmt-merge-msg.c b/builtin-fmt-merge-msg.c
index 65274824d3..f20b27b8a9 100644
--- a/builtin-fmt-merge-msg.c
+++ b/builtin-fmt-merge-msg.c
@@ -76,6 +76,7 @@ static int handle_line(char *line)
unsigned char *sha1;
char *src, *origin;
struct src_data *src_data;
+ int pulling_head = 0;
if (len < 43 || line[40] != '\t')
return 1;
@@ -101,8 +102,11 @@ static int handle_line(char *line)
if (src) {
*src = 0;
src += 4;
- } else
- src = "HEAD";
+ pulling_head = 0;
+ } else {
+ src = line;
+ pulling_head = 1;
+ }
i = find_in_list(&srcs, src);
if (i < 0) {
@@ -112,7 +116,10 @@ static int handle_line(char *line)
}
src_data = srcs.payload[i];
- if (!strncmp(line, "branch ", 7)) {
+ if (pulling_head) {
+ origin = strdup(src);
+ src_data->head_status |= 1;
+ } else if (!strncmp(line, "branch ", 7)) {
origin = strdup(line + 7);
append_to_list(&src_data->branch, origin, NULL);
src_data->head_status |= 2;
@@ -124,9 +131,6 @@ static int handle_line(char *line)
origin = strdup(line + 14);
append_to_list(&src_data->r_branch, origin, NULL);
src_data->head_status |= 2;
- } else if (!strcmp(line, "HEAD")) {
- origin = strdup(src);
- src_data->head_status |= 1;
} else {
origin = strdup(src);
append_to_list(&src_data->generic, strdup(line), NULL);
@@ -177,7 +181,7 @@ static void shortlog(const char *name, unsigned char *sha1,
int flags = UNINTERESTING | TREECHANGE | SEEN | SHOWN | ADDED;
branch = deref_tag(parse_object(sha1), sha1_to_hex(sha1), 40);
- if (!branch || branch->type != TYPE_COMMIT)
+ if (!branch || branch->type != OBJ_COMMIT)
return;
setup_revisions(0, NULL, rev, NULL);
diff --git a/builtin-grep.c b/builtin-grep.c
index 4c2f7dfe03..a79bac305a 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -891,9 +891,9 @@ static int grep_tree(struct grep_opt *opt, const char **paths,
static int grep_object(struct grep_opt *opt, const char **paths,
struct object *obj, const char *name)
{
- if (obj->type == TYPE_BLOB)
+ if (obj->type == OBJ_BLOB)
return grep_sha1(opt, obj->sha1, name);
- if (obj->type == TYPE_COMMIT || obj->type == TYPE_TREE) {
+ if (obj->type == OBJ_COMMIT || obj->type == OBJ_TREE) {
struct tree_desc tree;
void *data;
int hit;
diff --git a/builtin-prune.c b/builtin-prune.c
new file mode 100644
index 0000000000..d196c41f13
--- /dev/null
+++ b/builtin-prune.c
@@ -0,0 +1,259 @@
+#include "cache.h"
+#include "refs.h"
+#include "tag.h"
+#include "commit.h"
+#include "tree.h"
+#include "blob.h"
+#include "tree-walk.h"
+#include "diff.h"
+#include "revision.h"
+#include "builtin.h"
+#include "cache-tree.h"
+
+static const char prune_usage[] = "git prune [-n]";
+static int show_only = 0;
+static struct rev_info revs;
+
+static int prune_object(char *path, const char *filename, const unsigned char *sha1)
+{
+ if (show_only) {
+ printf("would prune %s/%s\n", path, filename);
+ return 0;
+ }
+ unlink(mkpath("%s/%s", path, filename));
+ rmdir(path);
+ return 0;
+}
+
+static int prune_dir(int i, char *path)
+{
+ DIR *dir = opendir(path);
+ struct dirent *de;
+
+ if (!dir)
+ return 0;
+
+ while ((de = readdir(dir)) != NULL) {
+ char name[100];
+ unsigned char sha1[20];
+ int len = strlen(de->d_name);
+
+ switch (len) {
+ case 2:
+ if (de->d_name[1] != '.')
+ break;
+ case 1:
+ if (de->d_name[0] != '.')
+ break;
+ continue;
+ case 38:
+ sprintf(name, "%02x", i);
+ memcpy(name+2, de->d_name, len+1);
+ if (get_sha1_hex(name, sha1) < 0)
+ break;
+
+ /*
+ * Do we know about this object?
+ * It must have been reachable
+ */
+ if (lookup_object(sha1))
+ continue;
+
+ prune_object(path, de->d_name, sha1);
+ continue;
+ }
+ fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name);
+ }
+ closedir(dir);
+ return 0;
+}
+
+static void prune_object_dir(const char *path)
+{
+ int i;
+ for (i = 0; i < 256; i++) {
+ static char dir[4096];
+ sprintf(dir, "%s/%02x", path, i);
+ prune_dir(i, dir);
+ }
+}
+
+static void process_blob(struct blob *blob,
+ struct object_array *p,
+ struct name_path *path,
+ const char *name)
+{
+ struct object *obj = &blob->object;
+
+ if (obj->flags & SEEN)
+ return;
+ obj->flags |= SEEN;
+ /* Nothing to do, really .. The blob lookup was the important part */
+}
+
+static void process_tree(struct tree *tree,
+ struct object_array *p,
+ struct name_path *path,
+ const char *name)
+{
+ struct object *obj = &tree->object;
+ struct tree_desc desc;
+ struct name_entry entry;
+ struct name_path me;
+
+ if (obj->flags & SEEN)
+ return;
+ obj->flags |= SEEN;
+ if (parse_tree(tree) < 0)
+ die("bad tree object %s", sha1_to_hex(obj->sha1));
+ name = strdup(name);
+ add_object(obj, p, path, name);
+ me.up = path;
+ me.elem = name;
+ me.elem_len = strlen(name);
+
+ desc.buf = tree->buffer;
+ desc.size = tree->size;
+
+ while (tree_entry(&desc, &entry)) {
+ if (S_ISDIR(entry.mode))
+ process_tree(lookup_tree(entry.sha1), p, &me, entry.path);
+ else
+ process_blob(lookup_blob(entry.sha1), p, &me, entry.path);
+ }
+ free(tree->buffer);
+ tree->buffer = NULL;
+}
+
+static void process_tag(struct tag *tag, struct object_array *p, const char *name)
+{
+ struct object *obj = &tag->object;
+ struct name_path me;
+
+ if (obj->flags & SEEN)
+ return;
+ obj->flags |= SEEN;
+
+ me.up = NULL;
+ me.elem = "tag:/";
+ me.elem_len = 5;
+
+ if (parse_tag(tag) < 0)
+ die("bad tag object %s", sha1_to_hex(obj->sha1));
+ add_object(tag->tagged, p, NULL, name);
+}
+
+static void walk_commit_list(struct rev_info *revs)
+{
+ int i;
+ struct commit *commit;
+ struct object_array objects = { 0, 0, NULL };
+
+ /* Walk all commits, process their trees */
+ while ((commit = get_revision(revs)) != NULL)
+ process_tree(commit->tree, &objects, NULL, "");
+
+ /* Then walk all the pending objects, recursively processing them too */
+ for (i = 0; i < revs->pending.nr; i++) {
+ struct object_array_entry *pending = revs->pending.objects + i;
+ struct object *obj = pending->item;
+ const char *name = pending->name;
+ if (obj->type == OBJ_TAG) {
+ process_tag((struct tag *) obj, &objects, name);
+ continue;
+ }
+ if (obj->type == OBJ_TREE) {
+ process_tree((struct tree *)obj, &objects, NULL, name);
+ continue;
+ }
+ if (obj->type == OBJ_BLOB) {
+ process_blob((struct blob *)obj, &objects, NULL, name);
+ continue;
+ }
+ die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name);
+ }
+}
+
+static int add_one_ref(const char *path, const unsigned char *sha1)
+{
+ struct object *object = parse_object(sha1);
+ if (!object)
+ die("bad object ref: %s:%s", path, sha1_to_hex(sha1));
+ add_pending_object(&revs, object, "");
+ return 0;
+}
+
+static void add_one_tree(const unsigned char *sha1)
+{
+ struct tree *tree = lookup_tree(sha1);
+ add_pending_object(&revs, &tree->object, "");
+}
+
+static void add_cache_tree(struct cache_tree *it)
+{
+ int i;
+
+ if (it->entry_count >= 0)
+ add_one_tree(it->sha1);
+ for (i = 0; i < it->subtree_nr; i++)
+ add_cache_tree(it->down[i]->cache_tree);
+}
+
+static void add_cache_refs(void)
+{
+ int i;
+
+ read_cache();
+ for (i = 0; i < active_nr; i++) {
+ lookup_blob(active_cache[i]->sha1);
+ /*
+ * We could add the blobs to the pending list, but quite
+ * frankly, we don't care. Once we've looked them up, and
+ * added them as objects, we've really done everything
+ * there is to do for a blob
+ */
+ }
+ if (active_cache_tree)
+ add_cache_tree(active_cache_tree);
+}
+
+int cmd_prune(int argc, const char **argv, char **envp)
+{
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ const char *arg = argv[i];
+ if (!strcmp(arg, "-n")) {
+ show_only = 1;
+ continue;
+ }
+ usage(prune_usage);
+ }
+
+ /*
+ * Set up revision parsing, and mark us as being interested
+ * in all object types, not just commits.
+ */
+ init_revisions(&revs);
+ revs.tag_objects = 1;
+ revs.blob_objects = 1;
+ revs.tree_objects = 1;
+
+ /* Add all external refs */
+ for_each_ref(add_one_ref);
+
+ /* Add all refs from the index file */
+ add_cache_refs();
+
+ /*
+ * Set up the revision walk - this will move all commits
+ * from the pending list to the commit walking list.
+ */
+ prepare_revision_walk(&revs);
+
+ walk_commit_list(&revs);
+
+ prune_object_dir(get_object_directory());
+
+ return 0;
+}
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 63bad0e96a..8f32871337 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -167,16 +167,16 @@ static void show_commit_list(struct rev_info *revs)
const char *name = pending->name;
if (obj->flags & (UNINTERESTING | SEEN))
continue;
- if (obj->type == TYPE_TAG) {
+ if (obj->type == OBJ_TAG) {
obj->flags |= SEEN;
add_object_array(obj, name, &objects);
continue;
}
- if (obj->type == TYPE_TREE) {
+ if (obj->type == OBJ_TREE) {
process_tree((struct tree *)obj, &objects, NULL, name);
continue;
}
- if (obj->type == TYPE_BLOB) {
+ if (obj->type == OBJ_BLOB) {
process_blob((struct blob *)obj, &objects, NULL, name);
continue;
}
diff --git a/builtin-show-branch.c b/builtin-show-branch.c
index 260cb221b9..3d240ca435 100644
--- a/builtin-show-branch.c
+++ b/builtin-show-branch.c
@@ -172,7 +172,7 @@ static void name_commits(struct commit_list *list,
static int mark_seen(struct commit *commit, struct commit_list **seen_p)
{
if (!commit->object.flags) {
- insert_by_date(commit, seen_p);
+ commit_list_insert(commit, seen_p);
return 1;
}
return 0;
@@ -218,9 +218,8 @@ static void join_revs(struct commit_list **list_p,
* Postprocess to complete well-poisoning.
*
* At this point we have all the commits we have seen in
- * seen_p list (which happens to be sorted chronologically but
- * it does not really matter). Mark anything that can be
- * reached from uninteresting commits not interesting.
+ * seen_p list. Mark anything that can be reached from
+ * uninteresting commits not interesting.
*/
for (;;) {
int changed = 0;
@@ -701,6 +700,8 @@ int cmd_show_branch(int ac, const char **av, char **envp)
if (0 <= extra)
join_revs(&list, &seen, num_rev, extra);
+ sort_by_date(&seen);
+
if (merge_base)
return show_merge_base(seen, num_rev);
diff --git a/builtin.h b/builtin.h
index d9e5483bd5..5339d8627f 100644
--- a/builtin.h
+++ b/builtin.h
@@ -25,6 +25,8 @@ extern int cmd_diff(int argc, const char **argv, char **envp);
extern int cmd_format_patch(int argc, const char **argv, char **envp);
extern int cmd_count_objects(int argc, const char **argv, char **envp);
+extern int cmd_prune(int argc, const char **argv, char **envp);
+
extern int cmd_push(int argc, const char **argv, char **envp);
extern int cmd_grep(int argc, const char **argv, char **envp);
extern int cmd_rm(int argc, const char **argv, char **envp);
diff --git a/commit.c b/commit.c
index c6bf10d045..77f0ca175c 100644
--- a/commit.c
+++ b/commit.c
@@ -56,7 +56,7 @@ static struct commit *check_commit(struct object *obj,
const unsigned char *sha1,
int quiet)
{
- if (obj->type != TYPE_COMMIT) {
+ if (obj->type != OBJ_COMMIT) {
if (!quiet)
error("Object %s is a %s, not a commit",
sha1_to_hex(sha1), typename(obj->type));
@@ -86,11 +86,11 @@ struct commit *lookup_commit(const unsigned char *sha1)
if (!obj) {
struct commit *ret = alloc_commit_node();
created_object(sha1, &ret->object);
- ret->object.type = TYPE_COMMIT;
+ ret->object.type = OBJ_COMMIT;
return ret;
}
if (!obj->type)
- obj->type = TYPE_COMMIT;
+ obj->type = OBJ_COMMIT;
return check_commit(obj, sha1, 0);
}
@@ -655,6 +655,9 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit
continue;
}
+ if (!subject)
+ body = 1;
+
if (is_empty_line(line, &linelen)) {
if (!body)
continue;
@@ -662,8 +665,6 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit
continue;
if (fmt == CMIT_FMT_SHORT)
break;
- } else {
- body = 1;
}
if (subject) {
@@ -702,6 +703,12 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit
/* Make sure there is an EOLN for the non-oneline case */
if (fmt != CMIT_FMT_ONELINE)
buf[offset++] = '\n';
+ /*
+ * make sure there is another EOLN to separate the headers from whatever
+ * body the caller appends if we haven't already written a body
+ */
+ if (fmt == CMIT_FMT_EMAIL && !body)
+ buf[offset++] = '\n';
buf[offset] = '\0';
return offset;
}
@@ -854,6 +861,7 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo,
#define PARENT1 (1u<< 8)
#define PARENT2 (1u<< 9)
#define STALE (1u<<10)
+#define RESULT (1u<<11)
static struct commit *interesting(struct commit_list *list)
{
@@ -867,183 +875,42 @@ static struct commit *interesting(struct commit_list *list)
return NULL;
}
-/*
- * A pathological example of how this thing works.
- *
- * Suppose we had this commit graph, where chronologically
- * the timestamp on the commit are A <= B <= C <= D <= E <= F
- * and we are trying to figure out the merge base for E and F
- * commits.
- *
- * F
- * / \
- * E A D
- * \ / /
- * B /
- * \ /
- * C
- *
- * First we push E and F to list to be processed. E gets bit 1
- * and F gets bit 2. The list becomes:
- *
- * list=F(2) E(1), result=empty
- *
- * Then we pop F, the newest commit, from the list. Its flag is 2.
- * We scan its parents, mark them reachable from the side that F is
- * reachable from, and push them to the list:
- *
- * list=E(1) D(2) A(2), result=empty
- *
- * Next pop E and do the same.
- *
- * list=D(2) B(1) A(2), result=empty
- *
- * Next pop D and do the same.
- *
- * list=C(2) B(1) A(2), result=empty
- *
- * Next pop C and do the same.
- *
- * list=B(1) A(2), result=empty
- *
- * Now it is B's turn. We mark its parent, C, reachable from B's side,
- * and push it to the list:
- *
- * list=C(3) A(2), result=empty
- *
- * Now pop C and notice it has flags==3. It is placed on the result list,
- * and the list now contains:
- *
- * list=A(2), result=C(3)
- *
- * We pop A and do the same.
- *
- * list=B(3), result=C(3)
- *
- * Next, we pop B and something very interesting happens. It has flags==3
- * so it is also placed on the result list, and its parents are marked
- * stale, retroactively, and placed back on the list:
- *
- * list=C(7), result=C(7) B(3)
- *
- * Now, list does not have any interesting commit. So we find the newest
- * commit from the result list that is not marked stale. Which is
- * commit B.
- *
- *
- * Another pathological example how this thing used to fail to mark an
- * ancestor of a merge base as STALE before we introduced the
- * postprocessing phase (mark_reachable_commits).
- *
- * 2
- * H
- * 1 / \
- * G A \
- * |\ / \
- * | B \
- * | \ \
- * \ C F
- * \ \ /
- * \ D /
- * \ | /
- * \| /
- * E
- *
- * list A B C D E F G H
- * G1 H2 - - - - - - 1 2
- * H2 E1 B1 - 1 - - 1 - 1 2
- * F2 E1 B1 A2 2 1 - - 1 2 1 2
- * E3 B1 A2 2 1 - - 3 2 1 2
- * B1 A2 2 1 - - 3 2 1 2
- * C1 A2 2 1 1 - 3 2 1 2
- * D1 A2 2 1 1 1 3 2 1 2
- * A2 2 1 1 1 3 2 1 2
- * B3 2 3 1 1 3 2 1 2
- * C7 2 3 7 1 3 2 1 2
- *
- * At this point, unfortunately, everybody in the list is
- * stale, so we fail to complete the following two
- * steps to fully marking stale commits.
- *
- * D7 2 3 7 7 3 2 1 2
- * E7 2 3 7 7 7 2 1 2
- *
- * and we ended up showing E as an interesting merge base.
- * The postprocessing phase re-injects C and continues traversal
- * to contaminate D and E.
- */
-
-static void mark_reachable_commits(struct commit_list *result,
- struct commit_list *list)
-{
- struct commit_list *tmp;
-
- /*
- * Postprocess to fully contaminate the well.
- */
- for (tmp = result; tmp; tmp = tmp->next) {
- struct commit *c = tmp->item;
- /* Reinject stale ones to list,
- * so we can scan their parents.
- */
- if (c->object.flags & STALE)
- commit_list_insert(c, &list);
- }
- while (list) {
- struct commit *c = list->item;
- struct commit_list *parents;
-
- tmp = list;
- list = list->next;
- free(tmp);
-
- /* Anything taken out of the list is stale, so
- * mark all its parents stale. We do not
- * parse new ones (we already parsed all the relevant
- * ones).
- */
- parents = c->parents;
- while (parents) {
- struct commit *p = parents->item;
- parents = parents->next;
- if (!(p->object.flags & STALE)) {
- p->object.flags |= STALE;
- commit_list_insert(p, &list);
- }
- }
- }
-}
-
-struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2,
- int cleanup)
+static struct commit_list *merge_bases(struct commit *one, struct commit *two)
{
struct commit_list *list = NULL;
struct commit_list *result = NULL;
- struct commit_list *tmp = NULL;
- if (rev1 == rev2)
- return commit_list_insert(rev1, &result);
+ if (one == two)
+ /* We do not mark this even with RESULT so we do not
+ * have to clean it up.
+ */
+ return commit_list_insert(one, &result);
- parse_commit(rev1);
- parse_commit(rev2);
+ parse_commit(one);
+ parse_commit(two);
- rev1->object.flags |= PARENT1;
- rev2->object.flags |= PARENT2;
- insert_by_date(rev1, &list);
- insert_by_date(rev2, &list);
+ one->object.flags |= PARENT1;
+ two->object.flags |= PARENT2;
+ insert_by_date(one, &list);
+ insert_by_date(two, &list);
while (interesting(list)) {
- struct commit *commit = list->item;
+ struct commit *commit;
struct commit_list *parents;
- int flags = commit->object.flags
- & (PARENT1 | PARENT2 | STALE);
+ struct commit_list *n;
+ int flags;
- tmp = list;
- list = list->next;
- free(tmp);
- if (flags == (PARENT1 | PARENT2)) {
- insert_by_date(commit, &result);
+ commit = list->item;
+ n = list->next;
+ free(list);
+ list = n;
+ flags = commit->object.flags & (PARENT1 | PARENT2 | STALE);
+ if (flags == (PARENT1 | PARENT2)) {
+ if (!(commit->object.flags & RESULT)) {
+ commit->object.flags |= RESULT;
+ insert_by_date(commit, &result);
+ }
/* Mark parents of a found merge stale */
flags |= STALE;
}
@@ -1059,35 +926,75 @@ struct commit_list *get_merge_bases(struct commit *rev1, struct commit *rev2,
}
}
- if (!result)
- goto finish;
-
- if (result->next && list)
- mark_reachable_commits(result, list);
-
- /* cull duplicates */
- for (tmp = result, list = NULL; tmp; ) {
- struct commit *commit = tmp->item;
- struct commit_list *next = tmp->next;
- if (commit->object.flags & STALE) {
- if (list != NULL)
- list->next = next;
- free(tmp);
- } else {
- if (list == NULL)
- result = tmp;
- list = tmp;
- commit->object.flags |= STALE;
- }
+ /* Clean up the result to remove stale ones */
+ list = result; result = NULL;
+ while (list) {
+ struct commit_list *n = list->next;
+ if (!(list->item->object.flags & STALE))
+ insert_by_date(list->item, &result);
+ free(list);
+ list = n;
+ }
+ return result;
+}
- tmp = next;
+struct commit_list *get_merge_bases(struct commit *one,
+ struct commit *two,
+ int cleanup)
+{
+ const unsigned all_flags = (PARENT1 | PARENT2 | STALE | RESULT);
+ struct commit_list *list;
+ struct commit **rslt;
+ struct commit_list *result;
+ int cnt, i, j;
+
+ result = merge_bases(one, two);
+ if (one == two)
+ return result;
+ if (!result || !result->next) {
+ if (cleanup) {
+ clear_commit_marks(one, all_flags);
+ clear_commit_marks(two, all_flags);
+ }
+ return result;
}
- finish:
- if (cleanup) {
- clear_commit_marks(rev1, PARENT1 | PARENT2 | STALE);
- clear_commit_marks(rev2, PARENT1 | PARENT2 | STALE);
+ /* There are more than one */
+ cnt = 0;
+ list = result;
+ while (list) {
+ list = list->next;
+ cnt++;
+ }
+ rslt = xcalloc(cnt, sizeof(*rslt));
+ for (list = result, i = 0; list; list = list->next)
+ rslt[i++] = list->item;
+ free_commit_list(result);
+
+ clear_commit_marks(one, all_flags);
+ clear_commit_marks(two, all_flags);
+ for (i = 0; i < cnt - 1; i++) {
+ for (j = i+1; j < cnt; j++) {
+ if (!rslt[i] || !rslt[j])
+ continue;
+ result = merge_bases(rslt[i], rslt[j]);
+ clear_commit_marks(rslt[i], all_flags);
+ clear_commit_marks(rslt[j], all_flags);
+ for (list = result; list; list = list->next) {
+ if (rslt[i] == list->item)
+ rslt[i] = NULL;
+ if (rslt[j] == list->item)
+ rslt[j] = NULL;
+ }
+ }
}
+ /* Surviving ones in rslt[] are the independent results */
+ result = NULL;
+ for (i = 0; i < cnt; i++) {
+ if (rslt[i])
+ insert_by_date(rslt[i], &result);
+ }
+ free(rslt);
return result;
}
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index ebd00ef9c4..34c995046d 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -59,14 +59,16 @@
(defcustom git-committer-name nil
"User name to use for commits.
-The default is to fall back to the repository config, then to `add-log-full-name' and then to `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 the git repository config, then to `add-log-mailing-address' and then to `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")))
@@ -86,6 +88,7 @@ The default is to fall back to the git repository config, then to `add-log-maili
:group 'git
:type 'string)
+
(defface git-status-face
'((((class color) (background light)) (:foreground "purple")))
"Git mode face used to highlight added and modified files."
@@ -149,7 +152,8 @@ The default is to fall back to the git repository config, then to `add-log-maili
(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."
+ "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))))
@@ -939,6 +943,8 @@ The default is to fall back to the git repository config, then to `add-log-maili
(let ((map (make-keymap))
(diff-map (make-sparse-keymap)))
(suppress-keymap map)
+ (define-key map "?" 'git-help)
+ (define-key map "h" 'git-help)
(define-key map " " 'git-next-file)
(define-key map "a" 'git-add-file)
(define-key map "c" 'git-commit-file)
@@ -1008,5 +1014,10 @@ Commands:
(goto-char (point-min)))
(message "%s is not a git working tree." dir)))
+(defun git-help ()
+ "Display help for Git mode."
+ (interactive)
+ (describe-function 'git-status-mode))
+
(provide 'git)
;;; git.el ends here
diff --git a/daemon.c b/daemon.c
index e096bd7ef6..e4ec676301 100644
--- a/daemon.c
+++ b/daemon.c
@@ -95,6 +95,12 @@ static void loginfo(const char *err, ...)
va_end(params);
}
+static void NORETURN daemon_die(const char *err, va_list params)
+{
+ logreport(LOG_ERR, err, params);
+ exit(1);
+}
+
static int avoid_alias(char *p)
{
int sl, ndot;
@@ -656,6 +662,45 @@ static int service_loop(int socknum, int *socklist)
}
}
+/* if any standard file descriptor is missing open it to /dev/null */
+static void sanitize_stdfds(void)
+{
+ int fd = open("/dev/null", O_RDWR, 0);
+ while (fd != -1 && fd < 2)
+ fd = dup(fd);
+ if (fd == -1)
+ die("open /dev/null or dup failed: %s", strerror(errno));
+ if (fd > 2)
+ close(fd);
+}
+
+static void daemonize(void)
+{
+ switch (fork()) {
+ case 0:
+ break;
+ case -1:
+ die("fork failed: %s", strerror(errno));
+ default:
+ exit(0);
+ }
+ if (setsid() == -1)
+ die("setsid failed: %s", strerror(errno));
+ close(0);
+ close(1);
+ close(2);
+ sanitize_stdfds();
+}
+
+static void store_pid(const char *path)
+{
+ FILE *f = fopen(path, "w");
+ if (!f)
+ die("cannot open pid file %s: %s", path, strerror(errno));
+ fprintf(f, "%d\n", getpid());
+ fclose(f);
+}
+
static int serve(int port)
{
int socknum, *socklist;
@@ -671,6 +716,8 @@ int main(int argc, char **argv)
{
int port = DEFAULT_GIT_PORT;
int inetd_mode = 0;
+ const char *pid_file = NULL;
+ int detach = 0;
int i;
/* Without this we cannot rely on waitpid() to tell
@@ -735,6 +782,15 @@ int main(int argc, char **argv)
user_path = arg + 12;
continue;
}
+ if (!strncmp(arg, "--pid-file=", 11)) {
+ pid_file = arg + 11;
+ continue;
+ }
+ if (!strcmp(arg, "--detach")) {
+ detach = 1;
+ log_syslog = 1;
+ continue;
+ }
if (!strcmp(arg, "--")) {
ok_paths = &argv[i+1];
break;
@@ -746,17 +802,14 @@ int main(int argc, char **argv)
usage(daemon_usage);
}
- if (log_syslog)
+ if (log_syslog) {
openlog("git-daemon", 0, LOG_DAEMON);
-
- if (strict_paths && (!ok_paths || !*ok_paths)) {
- if (!inetd_mode)
- die("git-daemon: option --strict-paths requires a whitelist");
-
- logerror("option --strict-paths requires a whitelist");
- exit (1);
+ set_die_routine(daemon_die);
}
+ if (strict_paths && (!ok_paths || !*ok_paths))
+ die("option --strict-paths requires a whitelist");
+
if (inetd_mode) {
struct sockaddr_storage ss;
struct sockaddr *peer = (struct sockaddr *)&ss;
@@ -770,5 +823,13 @@ int main(int argc, char **argv)
return execute(peer);
}
+ if (detach)
+ daemonize();
+ else
+ sanitize_stdfds();
+
+ if (pid_file)
+ store_pid(pid_file);
+
return serve(port);
}
diff --git a/describe.c b/describe.c
index 8e68d5df33..324ca8965b 100644
--- a/describe.c
+++ b/describe.c
@@ -67,7 +67,7 @@ static int get_name(const char *path, const unsigned char *sha1)
* Otherwise only annotated tags are used.
*/
if (!strncmp(path, "refs/tags/", 10)) {
- if (object->type == TYPE_TAG)
+ if (object->type == OBJ_TAG)
prio = 2;
else
prio = 1;
diff --git a/diff.c b/diff.c
index 287a927ce3..8b44756136 100644
--- a/diff.c
+++ b/diff.c
@@ -26,30 +26,14 @@ enum color_diff {
DIFF_FILE_NEW = 5,
};
-#define COLOR_NORMAL ""
-#define COLOR_BOLD "\033[1m"
-#define COLOR_DIM "\033[2m"
-#define COLOR_UL "\033[4m"
-#define COLOR_BLINK "\033[5m"
-#define COLOR_REVERSE "\033[7m"
-#define COLOR_RESET "\033[m"
-
-#define COLOR_BLACK "\033[30m"
-#define COLOR_RED "\033[31m"
-#define COLOR_GREEN "\033[32m"
-#define COLOR_YELLOW "\033[33m"
-#define COLOR_BLUE "\033[34m"
-#define COLOR_MAGENTA "\033[35m"
-#define COLOR_CYAN "\033[36m"
-#define COLOR_WHITE "\033[37m"
-
-static const char *diff_colors[] = {
- COLOR_RESET,
- COLOR_NORMAL,
- COLOR_BOLD,
- COLOR_CYAN,
- COLOR_RED,
- COLOR_GREEN
+/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
+static char diff_colors[][24] = {
+ "\033[m", /* reset */
+ "", /* normal */
+ "\033[1m", /* bold */
+ "\033[36m", /* cyan */
+ "\033[31m", /* red */
+ "\033[32m" /* green */
};
static int parse_diff_color_slot(const char *var, int ofs)
@@ -67,38 +51,116 @@ static int parse_diff_color_slot(const char *var, int ofs)
die("bad config variable '%s'", var);
}
-static const char *parse_diff_color_value(const char *value, const char *var)
-{
- if (!strcasecmp(value, "normal"))
- return COLOR_NORMAL;
- if (!strcasecmp(value, "bold"))
- return COLOR_BOLD;
- if (!strcasecmp(value, "dim"))
- return COLOR_DIM;
- if (!strcasecmp(value, "ul"))
- return COLOR_UL;
- if (!strcasecmp(value, "blink"))
- return COLOR_BLINK;
- if (!strcasecmp(value, "reverse"))
- return COLOR_REVERSE;
- if (!strcasecmp(value, "reset"))
- return COLOR_RESET;
- if (!strcasecmp(value, "black"))
- return COLOR_BLACK;
- if (!strcasecmp(value, "red"))
- return COLOR_RED;
- if (!strcasecmp(value, "green"))
- return COLOR_GREEN;
- if (!strcasecmp(value, "yellow"))
- return COLOR_YELLOW;
- if (!strcasecmp(value, "blue"))
- return COLOR_BLUE;
- if (!strcasecmp(value, "magenta"))
- return COLOR_MAGENTA;
- if (!strcasecmp(value, "cyan"))
- return COLOR_CYAN;
- if (!strcasecmp(value, "white"))
- return COLOR_WHITE;
+static int parse_color(const char *name, int len)
+{
+ static const char * const color_names[] = {
+ "normal", "black", "red", "green", "yellow",
+ "blue", "magenta", "cyan", "white"
+ };
+ char *end;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(color_names); i++) {
+ const char *str = color_names[i];
+ if (!strncasecmp(name, str, len) && !str[len])
+ return i - 1;
+ }
+ i = strtol(name, &end, 10);
+ if (*name && !*end && i >= -1 && i <= 255)
+ return i;
+ return -2;
+}
+
+static int parse_attr(const char *name, int len)
+{
+ static const int attr_values[] = { 1, 2, 4, 5, 7 };
+ static const char * const attr_names[] = {
+ "bold", "dim", "ul", "blink", "reverse"
+ };
+ int i;
+ for (i = 0; i < ARRAY_SIZE(attr_names); i++) {
+ const char *str = attr_names[i];
+ if (!strncasecmp(name, str, len) && !str[len])
+ return attr_values[i];
+ }
+ return -1;
+}
+
+static void parse_diff_color_value(const char *value, const char *var, char *dst)
+{
+ const char *ptr = value;
+ int attr = -1;
+ int fg = -2;
+ int bg = -2;
+
+ if (!strcasecmp(value, "reset")) {
+ strcpy(dst, "\033[m");
+ return;
+ }
+
+ /* [fg [bg]] [attr] */
+ while (*ptr) {
+ const char *word = ptr;
+ int val, len = 0;
+
+ while (word[len] && !isspace(word[len]))
+ len++;
+
+ ptr = word + len;
+ while (*ptr && isspace(*ptr))
+ ptr++;
+
+ val = parse_color(word, len);
+ if (val >= -1) {
+ if (fg == -2) {
+ fg = val;
+ continue;
+ }
+ if (bg == -2) {
+ bg = val;
+ continue;
+ }
+ goto bad;
+ }
+ val = parse_attr(word, len);
+ if (val < 0 || attr != -1)
+ goto bad;
+ attr = val;
+ }
+
+ if (attr >= 0 || fg >= 0 || bg >= 0) {
+ int sep = 0;
+
+ *dst++ = '\033';
+ *dst++ = '[';
+ if (attr >= 0) {
+ *dst++ = '0' + attr;
+ sep++;
+ }
+ if (fg >= 0) {
+ if (sep++)
+ *dst++ = ';';
+ if (fg < 8) {
+ *dst++ = '3';
+ *dst++ = '0' + fg;
+ } else {
+ dst += sprintf(dst, "38;5;%d", fg);
+ }
+ }
+ if (bg >= 0) {
+ if (sep++)
+ *dst++ = ';';
+ if (bg < 8) {
+ *dst++ = '4';
+ *dst++ = '0' + bg;
+ } else {
+ dst += sprintf(dst, "48;5;%d", bg);
+ }
+ }
+ *dst++ = 'm';
+ }
+ *dst = 0;
+ return;
+bad:
die("bad config value '%s' for variable '%s'", value, var);
}
@@ -145,7 +207,7 @@ int git_diff_ui_config(const char *var, const char *value)
}
if (!strncmp(var, "diff.color.", 11)) {
int slot = parse_diff_color_slot(var, 11);
- diff_colors[slot] = parse_diff_color_value(value, var);
+ parse_diff_color_value(value, var, diff_colors[slot]);
return 0;
}
return git_default_config(var, value);
diff --git a/exec_cmd.c b/exec_cmd.c
index c1539d12ce..62f51fcd6e 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -1,5 +1,6 @@
#include "cache.h"
#include "exec_cmd.h"
+#include "quote.h"
#define MAX_ARGS 32
extern char **environ;
@@ -96,9 +97,27 @@ int execv_git_cmd(const char **argv)
tmp = argv[0];
argv[0] = git_command;
+ if (getenv("GIT_TRACE")) {
+ const char **p = argv;
+ fputs("trace: exec:", stderr);
+ while (*p) {
+ fputc(' ', stderr);
+ sq_quote_print(stderr, *p);
+ ++p;
+ }
+ putc('\n', stderr);
+ fflush(stderr);
+ }
+
/* execve() can only ever return if it fails */
execve(git_command, (char **)argv, environ);
+ if (getenv("GIT_TRACE")) {
+ fprintf(stderr, "trace: exec failed: %s\n",
+ strerror(errno));
+ fflush(stderr);
+ }
+
argv[0] = tmp;
}
return -1;
diff --git a/fetch-pack.c b/fetch-pack.c
index f2c51ebe4b..b7824dbed4 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -46,7 +46,7 @@ static int rev_list_insert_ref(const char *path, const unsigned char *sha1)
{
struct object *o = deref_tag(parse_object(sha1), path, 0);
- if (o && o->type == TYPE_COMMIT)
+ if (o && o->type == OBJ_COMMIT)
rev_list_push((struct commit *)o, SEEN);
return 0;
@@ -256,14 +256,14 @@ static int mark_complete(const char *path, const unsigned char *sha1)
{
struct object *o = parse_object(sha1);
- while (o && o->type == TYPE_TAG) {
+ while (o && o->type == OBJ_TAG) {
struct tag *t = (struct tag *) o;
if (!t->tagged)
break; /* broken repository */
o->flags |= COMPLETE;
o = parse_object(t->tagged->sha1);
}
- if (o && o->type == TYPE_COMMIT) {
+ if (o && o->type == OBJ_COMMIT) {
struct commit *commit = (struct commit *)o;
commit->object.flags |= COMPLETE;
insert_by_date(commit, &complete);
@@ -357,7 +357,7 @@ static int everything_local(struct ref **refs, int nr_match, char **match)
* in sync with the other side at some time after
* that (it is OK if we guess wrong here).
*/
- if (o->type == TYPE_COMMIT) {
+ if (o->type == OBJ_COMMIT) {
struct commit *commit = (struct commit *)o;
if (!cutoff || cutoff < commit->date)
cutoff = commit->date;
@@ -376,7 +376,7 @@ static int everything_local(struct ref **refs, int nr_match, char **match)
struct object *o = deref_tag(lookup_object(ref->old_sha1),
NULL, 0);
- if (!o || o->type != TYPE_COMMIT || !(o->flags & COMPLETE))
+ if (!o || o->type != OBJ_COMMIT || !(o->flags & COMPLETE))
continue;
if (!(o->flags & SEEN)) {
diff --git a/fetch.c b/fetch.c
index 238032b798..989d7a4788 100644
--- a/fetch.c
+++ b/fetch.c
@@ -118,20 +118,20 @@ static struct object_list **process_queue_end = &process_queue;
static int process_object(struct object *obj)
{
- if (obj->type == TYPE_COMMIT) {
+ if (obj->type == OBJ_COMMIT) {
if (process_commit((struct commit *)obj))
return -1;
return 0;
}
- if (obj->type == TYPE_TREE) {
+ if (obj->type == OBJ_TREE) {
if (process_tree((struct tree *)obj))
return -1;
return 0;
}
- if (obj->type == TYPE_BLOB) {
+ if (obj->type == OBJ_BLOB) {
return 0;
}
- if (obj->type == TYPE_TAG) {
+ if (obj->type == OBJ_TAG) {
if (process_tag((struct tag *)obj))
return -1;
return 0;
diff --git a/fsck-objects.c b/fsck-objects.c
index ef54a8a411..e167f4105f 100644
--- a/fsck-objects.c
+++ b/fsck-objects.c
@@ -297,13 +297,13 @@ static int fsck_sha1(unsigned char *sha1)
if (obj->flags & SEEN)
return 0;
obj->flags |= SEEN;
- if (obj->type == TYPE_BLOB)
+ if (obj->type == OBJ_BLOB)
return 0;
- if (obj->type == TYPE_TREE)
+ if (obj->type == OBJ_TREE)
return fsck_tree((struct tree *) obj);
- if (obj->type == TYPE_COMMIT)
+ if (obj->type == OBJ_COMMIT)
return fsck_commit((struct commit *) obj);
- if (obj->type == TYPE_TAG)
+ if (obj->type == OBJ_TAG)
return fsck_tag((struct tag *) obj);
/* By now, parse_object() would've returned NULL instead. */
return objerror(obj, "unknown type '%d' (internal fsck error)", obj->type);
@@ -472,7 +472,7 @@ static int fsck_cache_tree(struct cache_tree *it)
}
mark_reachable(obj, REACHABLE);
obj->used = 1;
- if (obj->type != TYPE_TREE)
+ if (obj->type != OBJ_TREE)
err |= objerror(obj, "non-tree in cache-tree");
}
for (i = 0; i < it->subtree_nr; i++)
diff --git a/git-commit.sh b/git-commit.sh
index 802dd7243e..4cf3fab05c 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -138,32 +138,26 @@ run_status () {
if test -z "$untracked_files"; then
option="--directory --no-empty-directory"
fi
+ hdr_shown=
if test -f "$GIT_DIR/info/exclude"
then
- git-ls-files -z --others $option \
+ git-ls-files --others $option \
--exclude-from="$GIT_DIR/info/exclude" \
--exclude-per-directory=.gitignore
else
- git-ls-files -z --others $option \
+ git-ls-files --others $option \
--exclude-per-directory=.gitignore
fi |
- @@PERL@@ -e '$/ = "\0";
- my $shown = 0;
- while (<>) {
- chomp;
- s|\\|\\\\|g;
- s|\t|\\t|g;
- s|\n|\\n|g;
- s/^/# /;
- if (!$shown) {
- print "#\n# Untracked files:\n";
- print "# (use \"git add\" to add to commit)\n";
- print "#\n";
- $shown = 1;
- }
- print "$_\n";
- }
- '
+ while read line; do
+ if [ -z "$hdr_shown" ]; then
+ echo '#'
+ echo '# Untracked files:'
+ echo '# (use "git add" to add to commit)'
+ echo '#'
+ hdr_shown=1
+ fi
+ echo "# $line"
+ done
if test -n "$verbose" -a -z "$IS_INITIAL"
then
diff --git a/git-fetch.sh b/git-fetch.sh
index ff1769952b..ee99280a2a 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -153,7 +153,7 @@ fast_forward_local () {
then
if now_=$(cat "$GIT_DIR/$1") && test "$now_" = "$2"
then
- [ "$verbose" ] && echo >&2 "* $1: same as $3"
+ [ "$verbose" ] && echo >&2 "* $1: same as $3" ||:
else
echo >&2 "* $1: updating with $3"
git-update-ref -m "$rloga: updating tag" "$1" "$2"
diff --git a/git-prune.sh b/git-prune.sh
deleted file mode 100755
index c5a5d29aaa..0000000000
--- a/git-prune.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/sh
-
-USAGE='[-n] [--] [<head>...]'
-. git-sh-setup
-
-dryrun=
-echo=
-while case "$#" in 0) break ;; esac
-do
- case "$1" in
- -n) dryrun=-n echo=echo ;;
- --) break ;;
- -*) usage ;;
- *) break ;;
- esac
- shift;
-done
-
-sync
-case "$#" in
-0) git-fsck-objects --full --cache --unreachable ;;
-*) git-fsck-objects --full --cache --unreachable $(git-rev-parse --all) "$@" ;;
-esac |
-
-sed -ne '/unreachable /{
- s/unreachable [^ ][^ ]* //
- s|\(..\)|\1/|p
-}' | {
- cd "$GIT_OBJECT_DIRECTORY" || exit
- xargs $echo rm -f
- rmdir 2>/dev/null [0-9a-f][0-9a-f]
-}
-
-git-prune-packed $dryrun
-
-if redundant=$(git-pack-redundant --all 2>/dev/null) && test "" != "$redundant"
-then
- if test "" = "$dryrun"
- then
- echo "$redundant" | xargs rm -f
- else
- echo rm -f "$redundant"
- fi
-fi
diff --git a/git-repack.sh b/git-repack.sh
index 640ad8d90b..9da92fb061 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -43,7 +43,9 @@ case ",$all_into_one," in
;;
esac
pack_objects="$pack_objects $local $quiet $no_reuse_delta$extra"
-name=$(git-rev-list --objects --all $rev_list 2>&1 |
+name=$( { git-rev-list --objects --all $rev_list ||
+ echo "git-rev-list died with exit code $?"
+ } |
git-pack-objects --non-empty $pack_objects .tmp-pack) ||
exit 1
if [ -z "$name" ]; then
diff --git a/git-revert.sh b/git-revert.sh
index de8b5f0f0f..2bf35d116c 100755
--- a/git-revert.sh
+++ b/git-revert.sh
@@ -84,7 +84,7 @@ revert)
s/^[^ ]* /Revert "/
s/$/"/'
echo
- echo "This reverts $commit commit."
+ echo "This reverts commit $commit."
test "$rev" = "$commit" ||
echo "(original 'git revert' arguments: $@)"
base=$commit next=$prev
diff --git a/git-svn.perl b/git-svn.perl
index 4530ffe42c..89ad840dbf 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -147,7 +147,7 @@ init_vars();
load_authors() if $_authors;
load_all_refs() if $_branch_all_refs;
svn_compat_check() unless $_use_lib;
-migration_check() unless $cmd =~ /^(?:init|rebuild|multi-init)$/;
+migration_check() unless $cmd =~ /^(?:init|rebuild|multi-init|commit-diff)$/;
$cmd{$cmd}->[0]->(@ARGV);
exit 0;
diff --git a/git.c b/git.c
index 49062ca66e..ee5a0e86a7 100644
--- a/git.c
+++ b/git.c
@@ -11,6 +11,7 @@
#include "git-compat-util.h"
#include "exec_cmd.h"
#include "cache.h"
+#include "quote.h"
#include "builtin.h"
@@ -120,14 +121,25 @@ static int handle_alias(int *argcp, const char ***argv)
if (!strcmp(alias_command, new_argv[0]))
die("recursive alias: %s", alias_command);
- /* insert after command name */
- if (*argcp > 1) {
- new_argv = realloc(new_argv, sizeof(char*) *
- (count + *argcp));
- memcpy(new_argv + count, *argv + 1,
- sizeof(char*) * *argcp);
+ if (getenv("GIT_TRACE")) {
+ int i;
+ fprintf(stderr, "trace: alias expansion: %s =>",
+ alias_command);
+ for (i = 0; i < count; ++i) {
+ fputc(' ', stderr);
+ sq_quote_print(stderr, new_argv[i]);
+ }
+ fputc('\n', stderr);
+ fflush(stderr);
}
+ new_argv = realloc(new_argv, sizeof(char*) *
+ (count + *argcp + 1));
+ /* insert after command name */
+ memcpy(new_argv + count, *argv + 1,
+ sizeof(char*) * *argcp);
+ new_argv[count+*argcp] = NULL;
+
*argv = new_argv;
*argcp += count - 1;
@@ -188,7 +200,8 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "stripspace", cmd_stripspace },
{ "update-index", cmd_update_index },
{ "update-ref", cmd_update_ref },
- { "fmt-merge-msg", cmd_fmt_merge_msg }
+ { "fmt-merge-msg", cmd_fmt_merge_msg },
+ { "prune", cmd_prune },
};
int i;
@@ -202,6 +215,18 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
struct cmd_struct *p = commands+i;
if (strcmp(p->cmd, cmd))
continue;
+
+ if (getenv("GIT_TRACE")) {
+ int i;
+ fprintf(stderr, "trace: built-in: git");
+ for (i = 0; i < argc; ++i) {
+ fputc(' ', stderr);
+ sq_quote_print(stderr, argv[i]);
+ }
+ putc('\n', stderr);
+ fflush(stderr);
+ }
+
exit(p->fn(argc, argv, envp));
}
}
diff --git a/gitweb/gitweb.cgi b/gitweb/gitweb.cgi
index 2e87de4769..2fd1e5f78e 100755
--- a/gitweb/gitweb.cgi
+++ b/gitweb/gitweb.cgi
@@ -22,20 +22,16 @@ our $my_url = $cgi->url();
our $my_uri = $cgi->url(-absolute => 1);
our $rss_link = "";
-# location of the git-core binaries
-our $gitbin = "/usr/bin";
+# core git executable to use
+# this can just be "git" if your webserver has a sensible PATH
+our $GIT = "/usr/bin/git";
# absolute fs-path which will be prepended to the project path
#our $projectroot = "/pub/scm";
our $projectroot = "/home/kay/public_html/pub/scm";
-# version of the git-core binaries
-our $git_version = qx($gitbin/git --version);
-if ($git_version =~ m/git version (.*)$/) {
- $git_version = $1;
-} else {
- $git_version = "unknown";
-}
+# version of the core git binary
+our $git_version = qx($GIT --version) =~ m/git version (.*)$/ ? $1 : "unknown";
# location for temporary files needed for diffs
our $git_temp = "/tmp/gitweb";
@@ -46,6 +42,10 @@ if (! -d $git_temp) {
# target of the home link on top of all pages
our $home_link = $my_uri;
+# name of your site or organization to appear in page titles
+# replace this with something more descriptive for clearer bookmarks
+our $site_name = $ENV{'SERVER_NAME'} || "Untitled";
+
# html text to include at home page
our $home_text = "indextext.html";
@@ -280,7 +280,7 @@ sub git_header_html {
my $status = shift || "200 OK";
my $expires = shift;
- my $title = "git";
+ my $title = "$site_name git";
if (defined $project) {
$title .= " - $project";
if (defined $action) {
@@ -293,7 +293,17 @@ sub git_header_html {
}
}
}
- print $cgi->header(-type=>'text/html', -charset => 'utf-8', -status=> $status, -expires => $expires);
+ my $content_type;
+ # require explicit support from the UA if we are to send the page as
+ # 'application/xhtml+xml', otherwise send it as plain old 'text/html'.
+ # we have to do this because MSIE sometimes globs '*/*', pretending to
+ # support xhtml+xml but choking when it gets what it asked for.
+ if ($cgi->http('HTTP_ACCEPT') =~ m/(,|;|\s|^)application\/xhtml\+xml(,|;|\s|$)/ && $cgi->Accept('application/xhtml+xml') != 0) {
+ $content_type = 'application/xhtml+xml';
+ } else {
+ $content_type = 'text/html';
+ }
+ print $cgi->header(-type=>$content_type, -charset => 'utf-8', -status=> $status, -expires => $expires);
print <<EOF;
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
@@ -301,7 +311,7 @@ sub git_header_html {
<!-- git web interface v$version, (C) 2005-2006, Kay Sievers <kay.sievers\@vrfy.org>, Christian Gierke -->
<!-- git core binaries version $git_version -->
<head>
-<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
+<meta http-equiv="content-type" content="$content_type; charset=utf-8"/>
<meta name="robots" content="index, nofollow"/>
<title>$title</title>
<link rel="stylesheet" type="text/css" href="$stylesheet"/>
@@ -378,7 +388,7 @@ sub die_error {
sub git_get_type {
my $hash = shift;
- open my $fd, "-|", "$gitbin/git-cat-file -t $hash" or return;
+ open my $fd, "-|", "$GIT cat-file -t $hash" or return;
my $type = <$fd>;
close $fd or return;
chomp $type;
@@ -390,7 +400,7 @@ sub git_read_head {
my $oENV = $ENV{'GIT_DIR'};
my $retval = undef;
$ENV{'GIT_DIR'} = "$projectroot/$project";
- if (open my $fd, "-|", "$gitbin/git-rev-parse", "--verify", "HEAD") {
+ if (open my $fd, "-|", $GIT, "rev-parse", "--verify", "HEAD") {
my $head = <$fd>;
close $fd;
if (defined $head && $head =~ /^([0-9a-fA-F]{40})$/) {
@@ -430,7 +440,7 @@ sub git_read_tag {
my %tag;
my @comment;
- open my $fd, "-|", "$gitbin/git-cat-file tag $tag_id" or return;
+ open my $fd, "-|", "$GIT cat-file tag $tag_id" or return;
$tag{'id'} = $tag_id;
while (my $line = <$fd>) {
chomp $line;
@@ -502,7 +512,7 @@ sub git_read_commit {
@commit_lines = @$commit_text;
} else {
$/ = "\0";
- open my $fd, "-|", "$gitbin/git-rev-list --header --parents --max-count=1 $commit_id" or return;
+ open my $fd, "-|", "$GIT rev-list --header --parents --max-count=1 $commit_id" or return;
@commit_lines = split '\n', <$fd>;
close $fd or return;
$/ = "\n";
@@ -600,7 +610,7 @@ sub git_diff_print {
if (defined $from) {
$from_tmp = "$git_temp/gitweb_" . $$ . "_from";
open my $fd2, "> $from_tmp";
- open my $fd, "-|", "$gitbin/git-cat-file blob $from";
+ open my $fd, "-|", "$GIT cat-file blob $from";
my @file = <$fd>;
print $fd2 @file;
close $fd2;
@@ -611,7 +621,7 @@ sub git_diff_print {
if (defined $to) {
$to_tmp = "$git_temp/gitweb_" . $$ . "_to";
open my $fd2, "> $to_tmp";
- open my $fd, "-|", "$gitbin/git-cat-file blob $to";
+ open my $fd, "-|", "$GIT cat-file blob $to";
my @file = <$fd>;
print $fd2 @file;
close $fd2;
@@ -830,7 +840,7 @@ sub git_get_project_config {
$key =~ s/^gitweb\.//;
return if ($key =~ m/\W/);
- my $val = qx($gitbin/git-repo-config --get gitweb.$key);
+ my $val = qx($GIT repo-config --get gitweb.$key);
return ($val);
}
@@ -1052,7 +1062,7 @@ sub git_summary {
"<tr><td>owner</td><td>$owner</td></tr>\n" .
"<tr><td>last change</td><td>$cd{'rfc2822'}</td></tr>\n" .
"</table>\n";
- open my $fd, "-|", "$gitbin/git-rev-list --max-count=17 " . git_read_head($project) or die_error(undef, "Open failed.");
+ open my $fd, "-|", "$GIT rev-list --max-count=17 " . git_read_head($project) or die_error(undef, "Open failed.");
my (@revlist) = map { chomp; $_ } <$fd>;
close $fd;
print "<div>\n" .
@@ -1240,7 +1250,7 @@ sub git_blame {
$hash = git_get_hash_by_path($hash_base, $file_name, "blob")
or die_error(undef, "Error lookup file.");
}
- open ($fd, "-|", "$gitbin/git-annotate", '-l', '-t', '-r', $file_name, $hash_base)
+ open ($fd, "-|", $GIT, "annotate", '-l', '-t', '-r', $file_name, $hash_base)
or die_error(undef, "Open failed.");
git_header_html();
print "<div class=\"page_nav\">\n" .
@@ -1435,7 +1445,7 @@ sub git_get_hash_by_path {
my $tree = $base;
my @parts = split '/', $path;
while (my $part = shift @parts) {
- open my $fd, "-|", "$gitbin/git-ls-tree $tree" or die_error(undef, "Open git-ls-tree failed.");
+ open my $fd, "-|", "$GIT ls-tree $tree" or die_error(undef, "Open git-ls-tree failed.");
my (@entries) = map { chomp; $_ } <$fd>;
close $fd or return undef;
foreach my $line (@entries) {
@@ -1522,7 +1532,7 @@ sub git_blob_plain_mimetype {
sub git_blob_plain {
my $type = shift;
- open my $fd, "-|", "$gitbin/git-cat-file blob $hash" or die_error("Couldn't cat $file_name, $hash");
+ open my $fd, "-|", "$GIT cat-file blob $hash" or die_error("Couldn't cat $file_name, $hash");
$type ||= git_blob_plain_mimetype($fd, $file_name);
@@ -1549,7 +1559,7 @@ sub git_blob {
$hash = git_get_hash_by_path($base, $file_name, "blob") || die_error(undef, "Error lookup file.");
}
my $have_blame = git_get_project_config_bool ('blame');
- open my $fd, "-|", "$gitbin/git-cat-file blob $hash" or die_error(undef, "Open failed.");
+ open my $fd, "-|", "$GIT cat-file blob $hash" or die_error(undef, "Open failed.");
my $mimetype = git_blob_plain_mimetype($fd, $file_name);
if ($mimetype !~ m/^text\//) {
close $fd;
@@ -1615,7 +1625,7 @@ sub git_tree {
}
}
$/ = "\0";
- open my $fd, "-|", "$gitbin/git-ls-tree -z $hash" or die_error(undef, "Open git-ls-tree failed.");
+ open my $fd, "-|", "$GIT ls-tree -z $hash" or die_error(undef, "Open git-ls-tree failed.");
chomp (my (@entries) = <$fd>);
close $fd or die_error(undef, "Reading tree failed.");
$/ = "\n";
@@ -1698,7 +1708,7 @@ sub git_tree {
sub git_rss {
# http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ
- open my $fd, "-|", "$gitbin/git-rev-list --max-count=150 " . git_read_head($project) or die_error(undef, "Open failed.");
+ open my $fd, "-|", "$GIT rev-list --max-count=150 " . git_read_head($project) or die_error(undef, "Open failed.");
my (@revlist) = map { chomp; $_ } <$fd>;
close $fd or die_error(undef, "Reading rev-list failed.");
print $cgi->header(-type => 'text/xml', -charset => 'utf-8');
@@ -1718,7 +1728,7 @@ sub git_rss {
last;
}
my %cd = date_str($co{'committer_epoch'});
- open $fd, "-|", "$gitbin/git-diff-tree -r $co{'parent'} $co{'id'}" or next;
+ open $fd, "-|", "$GIT diff-tree -r $co{'parent'} $co{'id'}" or next;
my @difftree = map { chomp; $_ } <$fd>;
close $fd or next;
print "<item>\n" .
@@ -1760,7 +1770,7 @@ sub git_opml {
print "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n".
"<opml version=\"1.0\">\n".
"<head>".
- " <title>Git OPML Export</title>\n".
+ " <title>$site_name Git OPML Export</title>\n".
"</head>\n".
"<body>\n".
"<outline text=\"git RSS feeds\">\n";
@@ -1806,7 +1816,7 @@ sub git_log {
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$hash;hb=$hash")}, "tree") . "<br/>\n";
my $limit = sprintf("--max-count=%i", (100 * ($page+1)));
- open my $fd, "-|", "$gitbin/git-rev-list $limit $hash" or die_error(undef, "Open failed.");
+ open my $fd, "-|", "$GIT rev-list $limit $hash" or die_error(undef, "Open failed.");
my (@revlist) = map { chomp; $_ } <$fd>;
close $fd;
@@ -1897,7 +1907,7 @@ sub git_commit {
$root = " --root";
$parent = "";
}
- open my $fd, "-|", "$gitbin/git-diff-tree -r -M $root $parent $hash" or die_error(undef, "Open failed.");
+ open my $fd, "-|", "$GIT diff-tree -r -M $root $parent $hash" or die_error(undef, "Open failed.");
@difftree = map { chomp; $_ } <$fd>;
close $fd or die_error(undef, "Reading diff-tree failed.");
@@ -2139,7 +2149,7 @@ sub git_commitdiff {
if (!defined $hash_parent) {
$hash_parent = $co{'parent'};
}
- open my $fd, "-|", "$gitbin/git-diff-tree -r $hash_parent $hash" or die_error(undef, "Open failed.");
+ open my $fd, "-|", "$GIT diff-tree -r $hash_parent $hash" or die_error(undef, "Open failed.");
my (@difftree) = map { chomp; $_ } <$fd>;
close $fd or die_error(undef, "Reading diff-tree failed.");
@@ -2229,14 +2239,14 @@ sub git_commitdiff {
sub git_commitdiff_plain {
mkdir($git_temp, 0700);
- open my $fd, "-|", "$gitbin/git-diff-tree -r $hash_parent $hash" or die_error(undef, "Open failed.");
+ open my $fd, "-|", "$GIT diff-tree -r $hash_parent $hash" or die_error(undef, "Open failed.");
my (@difftree) = map { chomp; $_ } <$fd>;
close $fd or die_error(undef, "Reading diff-tree failed.");
# try to figure out the next tag after this commit
my $tagname;
my $refs = read_info_ref("tags");
- open $fd, "-|", "$gitbin/git-rev-list HEAD";
+ open $fd, "-|", "$GIT rev-list HEAD";
chomp (my (@commits) = <$fd>);
close $fd;
foreach my $commit (@commits) {
@@ -2307,7 +2317,7 @@ sub git_history {
print "<div class=\"page_path\"><b>/" . esc_html($file_name) . "</b><br/></div>\n";
open my $fd, "-|",
- "$gitbin/git-rev-list --full-history $hash -- \'$file_name\'";
+ "$GIT rev-list --full-history $hash -- \'$file_name\'";
print "<table cellspacing=\"0\">\n";
my $alternate = 0;
while (my $line = <$fd>) {
@@ -2394,7 +2404,7 @@ sub git_search {
my $alternate = 0;
if ($commit_search) {
$/ = "\0";
- open my $fd, "-|", "$gitbin/git-rev-list --header --parents $hash" or next;
+ open my $fd, "-|", "$GIT rev-list --header --parents $hash" or next;
while (my $commit_text = <$fd>) {
if (!grep m/$searchtext/i, $commit_text) {
next;
@@ -2444,7 +2454,7 @@ sub git_search {
if ($pickaxe_search) {
$/ = "\n";
- open my $fd, "-|", "$gitbin/git-rev-list $hash | $gitbin/git-diff-tree -r --stdin -S\'$searchtext\'";
+ open my $fd, "-|", "$GIT rev-list $hash | $GIT diff-tree -r --stdin -S\'$searchtext\'";
undef %co;
my @files;
while (my $line = <$fd>) {
@@ -2515,7 +2525,7 @@ sub git_shortlog {
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$hash;hb=$hash")}, "tree") . "<br/>\n";
my $limit = sprintf("--max-count=%i", (100 * ($page+1)));
- open my $fd, "-|", "$gitbin/git-rev-list $limit $hash" or die_error(undef, "Open failed.");
+ open my $fd, "-|", "$GIT rev-list $limit $hash" or die_error(undef, "Open failed.");
my (@revlist) = map { chomp; $_ } <$fd>;
close $fd;
diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css
index 98410f5b6c..fffdb13d09 100644
--- a/gitweb/gitweb.css
+++ b/gitweb/gitweb.css
@@ -60,6 +60,7 @@ div.page_footer_text {
div.page_body {
padding: 8px;
+ font-family: monospace;
}
div.title, a.title {
@@ -79,6 +80,7 @@ div.title_text {
padding: 6px 0px;
border: solid #d9d8d1;
border-width: 0px 0px 1px;
+ font-family: monospace;
}
div.log_body {
@@ -142,8 +144,13 @@ table {
padding: 8px 4px;
}
-table.project_list, table.diff_tree {
+table.project_list {
+ border-spacing: 0;
+}
+
+table.diff_tree {
border-spacing: 0;
+ font-family: monospace;
}
table.blame {
diff --git a/http-push.c b/http-push.c
index f761584d7e..47686195cd 100644
--- a/http-push.c
+++ b/http-push.c
@@ -1784,16 +1784,16 @@ static int get_delta(struct rev_info *revs, struct remote_lock *lock)
if (obj->flags & (UNINTERESTING | SEEN))
continue;
- if (obj->type == TYPE_TAG) {
+ if (obj->type == OBJ_TAG) {
obj->flags |= SEEN;
p = add_one_object(obj, p);
continue;
}
- if (obj->type == TYPE_TREE) {
+ if (obj->type == OBJ_TREE) {
p = process_tree((struct tree *)obj, p, NULL, name);
continue;
}
- if (obj->type == TYPE_BLOB) {
+ if (obj->type == OBJ_BLOB) {
p = process_blob((struct blob *)obj, p, NULL, name);
continue;
}
@@ -1960,12 +1960,12 @@ static int ref_newer(const unsigned char *new_sha1,
* old. Otherwise we require --force.
*/
o = deref_tag(parse_object(old_sha1), NULL, 0);
- if (!o || o->type != TYPE_COMMIT)
+ if (!o || o->type != OBJ_COMMIT)
return 0;
old = (struct commit *) o;
o = deref_tag(parse_object(new_sha1), NULL, 0);
- if (!o || o->type != TYPE_COMMIT)
+ if (!o || o->type != OBJ_COMMIT)
return 0;
new = (struct commit *) o;
@@ -2044,7 +2044,7 @@ static void add_remote_info_ref(struct remote_ls_ctx *ls)
fwrite_buffer(ref_info, 1, len, buf);
free(ref_info);
- if (o->type == TYPE_TAG) {
+ if (o->type == OBJ_TAG) {
o = deref_tag(o, ls->dentry_name, 0);
if (o) {
len = strlen(ls->dentry_name) + 45;
diff --git a/merge-file.c b/merge-file.c
new file mode 100644
index 0000000000..f32c653825
--- /dev/null
+++ b/merge-file.c
@@ -0,0 +1,166 @@
+#include "cache.h"
+#include "run-command.h"
+#include "xdiff-interface.h"
+#include "blob.h"
+
+static void rm_temp_file(const char *filename)
+{
+ unlink(filename);
+ free((void *)filename);
+}
+
+static const char *write_temp_file(mmfile_t *f)
+{
+ int fd;
+ const char *tmp = getenv("TMPDIR");
+ char *filename;
+
+ if (!tmp)
+ tmp = "/tmp";
+ filename = mkpath("%s/%s", tmp, "git-tmp-XXXXXX");
+ fd = mkstemp(filename);
+ if (fd < 0)
+ return NULL;
+ filename = strdup(filename);
+ if (f->size != xwrite(fd, f->ptr, f->size)) {
+ rm_temp_file(filename);
+ return NULL;
+ }
+ close(fd);
+ return filename;
+}
+
+static void *read_temp_file(const char *filename, unsigned long *size)
+{
+ struct stat st;
+ char *buf = NULL;
+ int fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+ if (!fstat(fd, &st)) {
+ *size = st.st_size;
+ buf = xmalloc(st.st_size);
+ if (st.st_size != xread(fd, buf, st.st_size)) {
+ free(buf);
+ buf = NULL;
+ }
+ }
+ close(fd);
+ return buf;
+}
+
+static int fill_mmfile_blob(mmfile_t *f, struct blob *obj)
+{
+ void *buf;
+ unsigned long size;
+ char type[20];
+
+ buf = read_sha1_file(obj->object.sha1, type, &size);
+ if (!buf)
+ return -1;
+ if (strcmp(type, blob_type))
+ return -1;
+ f->ptr = buf;
+ f->size = size;
+ return 0;
+}
+
+static void free_mmfile(mmfile_t *f)
+{
+ free(f->ptr);
+}
+
+static void *three_way_filemerge(mmfile_t *base, mmfile_t *our, mmfile_t *their, unsigned long *size)
+{
+ void *res;
+ const char *t1, *t2, *t3;
+
+ t1 = write_temp_file(base);
+ t2 = write_temp_file(our);
+ t3 = write_temp_file(their);
+ res = NULL;
+ if (t1 && t2 && t3) {
+ int code = run_command("merge", t2, t1, t3, NULL);
+ if (!code || code == -1)
+ res = read_temp_file(t2, size);
+ }
+ rm_temp_file(t1);
+ rm_temp_file(t2);
+ rm_temp_file(t3);
+ return res;
+}
+
+static int common_outf(void *priv_, mmbuffer_t *mb, int nbuf)
+{
+ int i;
+ mmfile_t *dst = priv_;
+
+ for (i = 0; i < nbuf; i++) {
+ memcpy(dst->ptr + dst->size, mb[i].ptr, mb[i].size);
+ dst->size += mb[i].size;
+ }
+ return 0;
+}
+
+static int generate_common_file(mmfile_t *res, mmfile_t *f1, mmfile_t *f2)
+{
+ unsigned long size = f1->size < f2->size ? f1->size : f2->size;
+ void *ptr = xmalloc(size);
+ xpparam_t xpp;
+ xdemitconf_t xecfg;
+ xdemitcb_t ecb;
+
+ xpp.flags = XDF_NEED_MINIMAL;
+ xecfg.ctxlen = 3;
+ xecfg.flags = XDL_EMIT_COMMON;
+ ecb.outf = common_outf;
+
+ res->ptr = ptr;
+ res->size = 0;
+
+ ecb.priv = res;
+ return xdl_diff(f1, f2, &xpp, &xecfg, &ecb);
+}
+
+void *merge_file(struct blob *base, struct blob *our, struct blob *their, unsigned long *size)
+{
+ void *res = NULL;
+ mmfile_t f1, f2, common;
+
+ /*
+ * Removed in either branch?
+ *
+ * NOTE! This depends on the caller having done the
+ * proper warning about removing a file that got
+ * modified in the other branch!
+ */
+ if (!our || !their) {
+ char type[20];
+ if (base)
+ return NULL;
+ if (!our)
+ our = their;
+ return read_sha1_file(our->object.sha1, type, size);
+ }
+
+ if (fill_mmfile_blob(&f1, our) < 0)
+ goto out_no_mmfile;
+ if (fill_mmfile_blob(&f2, their) < 0)
+ goto out_free_f1;
+
+ if (base) {
+ if (fill_mmfile_blob(&common, base) < 0)
+ goto out_free_f2_f1;
+ } else {
+ if (generate_common_file(&common, &f1, &f2) < 0)
+ goto out_free_f2_f1;
+ }
+ res = three_way_filemerge(&common, &f1, &f2, size);
+ free_mmfile(&common);
+out_free_f2_f1:
+ free_mmfile(&f2);
+out_free_f1:
+ free_mmfile(&f1);
+out_no_mmfile:
+ return res;
+}
diff --git a/merge-tree.c b/merge-tree.c
index 9dcaab7a85..7cf00be6d5 100644
--- a/merge-tree.c
+++ b/merge-tree.c
@@ -1,11 +1,152 @@
#include "cache.h"
#include "tree-walk.h"
+#include "xdiff-interface.h"
+#include "blob.h"
static const char merge_tree_usage[] = "git-merge-tree <base-tree> <branch1> <branch2>";
static int resolve_directories = 1;
+struct merge_list {
+ struct merge_list *next;
+ struct merge_list *link; /* other stages for this object */
+
+ unsigned int stage : 2,
+ flags : 30;
+ unsigned int mode;
+ const char *path;
+ struct blob *blob;
+};
+
+static struct merge_list *merge_result, **merge_result_end = &merge_result;
+
+static void add_merge_entry(struct merge_list *entry)
+{
+ *merge_result_end = entry;
+ merge_result_end = &entry->next;
+}
+
static void merge_trees(struct tree_desc t[3], const char *base);
+static const char *explanation(struct merge_list *entry)
+{
+ switch (entry->stage) {
+ case 0:
+ return "merged";
+ case 3:
+ return "added in remote";
+ case 2:
+ if (entry->link)
+ return "added in both";
+ return "added in local";
+ }
+
+ /* Existed in base */
+ entry = entry->link;
+ if (!entry)
+ return "removed in both";
+
+ if (entry->link)
+ return "changed in both";
+
+ if (entry->stage == 3)
+ return "removed in local";
+ return "removed in remote";
+}
+
+extern void *merge_file(struct blob *, struct blob *, struct blob *, unsigned long *);
+
+static void *result(struct merge_list *entry, unsigned long *size)
+{
+ char type[20];
+ struct blob *base, *our, *their;
+
+ if (!entry->stage)
+ return read_sha1_file(entry->blob->object.sha1, type, size);
+ base = NULL;
+ if (entry->stage == 1) {
+ base = entry->blob;
+ entry = entry->link;
+ }
+ our = NULL;
+ if (entry && entry->stage == 2) {
+ our = entry->blob;
+ entry = entry->link;
+ }
+ their = NULL;
+ if (entry)
+ their = entry->blob;
+ return merge_file(base, our, their, size);
+}
+
+static void *origin(struct merge_list *entry, unsigned long *size)
+{
+ char type[20];
+ while (entry) {
+ if (entry->stage == 2)
+ return read_sha1_file(entry->blob->object.sha1, type, size);
+ entry = entry->link;
+ }
+ return NULL;
+}
+
+static int show_outf(void *priv_, mmbuffer_t *mb, int nbuf)
+{
+ int i;
+ for (i = 0; i < nbuf; i++)
+ printf("%.*s", (int) mb[i].size, mb[i].ptr);
+ return 0;
+}
+
+static void show_diff(struct merge_list *entry)
+{
+ unsigned long size;
+ mmfile_t src, dst;
+ xpparam_t xpp;
+ xdemitconf_t xecfg;
+ xdemitcb_t ecb;
+
+ xpp.flags = XDF_NEED_MINIMAL;
+ xecfg.ctxlen = 3;
+ xecfg.flags = 0;
+ ecb.outf = show_outf;
+ ecb.priv = NULL;
+
+ src.ptr = origin(entry, &size);
+ if (!src.ptr)
+ size = 0;
+ src.size = size;
+ dst.ptr = result(entry, &size);
+ if (!dst.ptr)
+ size = 0;
+ dst.size = size;
+ xdl_diff(&src, &dst, &xpp, &xecfg, &ecb);
+ free(src.ptr);
+ free(dst.ptr);
+}
+
+static void show_result_list(struct merge_list *entry)
+{
+ printf("%s\n", explanation(entry));
+ do {
+ struct merge_list *link = entry->link;
+ static const char *desc[4] = { "result", "base", "our", "their" };
+ printf(" %-6s %o %s %s\n", desc[entry->stage], entry->mode, sha1_to_hex(entry->blob->object.sha1), entry->path);
+ entry = link;
+ } while (entry);
+}
+
+static void show_result(void)
+{
+ struct merge_list *walk;
+
+ walk = merge_result;
+ while (walk) {
+ show_result_list(walk);
+ show_diff(walk);
+ walk = walk->next;
+ }
+}
+
/* An empty entry never compares same, not even to another empty entry */
static int same_entry(struct name_entry *a, struct name_entry *b)
{
@@ -15,24 +156,34 @@ static int same_entry(struct name_entry *a, struct name_entry *b)
a->mode == b->mode;
}
-static const char *sha1_to_hex_zero(const unsigned char *sha1)
+static struct merge_list *create_entry(unsigned stage, unsigned mode, const unsigned char *sha1, const char *path)
{
- if (sha1)
- return sha1_to_hex(sha1);
- return "0000000000000000000000000000000000000000";
+ struct merge_list *res = xmalloc(sizeof(*res));
+
+ memset(res, 0, sizeof(*res));
+ res->stage = stage;
+ res->path = path;
+ res->mode = mode;
+ res->blob = lookup_blob(sha1);
+ return res;
}
static void resolve(const char *base, struct name_entry *branch1, struct name_entry *result)
{
+ struct merge_list *orig, *final;
+ const char *path;
+
/* If it's already branch1, don't bother showing it */
if (!branch1)
return;
- printf("0 %06o->%06o %s->%s %s%s\n",
- branch1->mode, result->mode,
- sha1_to_hex_zero(branch1->sha1),
- sha1_to_hex_zero(result->sha1),
- base, result->path);
+ path = strdup(mkpath("%s%s", base, result->path));
+ orig = create_entry(2, branch1->mode, branch1->sha1, path);
+ final = create_entry(0, result->mode, result->sha1, path);
+
+ final->link = orig;
+
+ add_merge_entry(final);
}
static int unresolved_directory(const char *base, struct name_entry n[3])
@@ -71,16 +222,40 @@ static int unresolved_directory(const char *base, struct name_entry n[3])
return 1;
}
+
+static struct merge_list *link_entry(unsigned stage, const char *base, struct name_entry *n, struct merge_list *entry)
+{
+ const char *path;
+ struct merge_list *link;
+
+ if (!n->mode)
+ return entry;
+ if (entry)
+ path = entry->path;
+ else
+ path = strdup(mkpath("%s%s", base, n->path));
+ link = create_entry(stage, n->mode, n->sha1, path);
+ link->link = entry;
+ return link;
+}
+
static void unresolved(const char *base, struct name_entry n[3])
{
+ struct merge_list *entry = NULL;
+
if (unresolved_directory(base, n))
return;
- if (n[0].sha1)
- printf("1 %06o %s %s%s\n", n[0].mode, sha1_to_hex(n[0].sha1), base, n[0].path);
- if (n[1].sha1)
- printf("2 %06o %s %s%s\n", n[1].mode, sha1_to_hex(n[1].sha1), base, n[1].path);
- if (n[2].sha1)
- printf("3 %06o %s %s%s\n", n[2].mode, sha1_to_hex(n[2].sha1), base, n[2].path);
+
+ /*
+ * Do them in reverse order so that the resulting link
+ * list has the stages in order - link_entry adds new
+ * links at the front.
+ */
+ entry = link_entry(3, base, n + 2, entry);
+ entry = link_entry(2, base, n + 1, entry);
+ entry = link_entry(1, base, n + 0, entry);
+
+ add_merge_entry(entry);
}
/*
@@ -172,5 +347,7 @@ int main(int argc, char **argv)
free(buf1);
free(buf2);
free(buf3);
+
+ show_result();
return 0;
}
diff --git a/name-rev.c b/name-rev.c
index 083d067e17..f92f14e32f 100644
--- a/name-rev.c
+++ b/name-rev.c
@@ -84,14 +84,14 @@ static int name_ref(const char *path, const unsigned char *sha1)
if (tags_only && strncmp(path, "refs/tags/", 10))
return 0;
- while (o && o->type == TYPE_TAG) {
+ while (o && o->type == OBJ_TAG) {
struct tag *t = (struct tag *) o;
if (!t->tagged)
break; /* broken repository */
o = parse_object(t->tagged->sha1);
deref = 1;
}
- if (o && o->type == TYPE_COMMIT) {
+ if (o && o->type == OBJ_COMMIT) {
struct commit *commit = (struct commit *)o;
if (!strncmp(path, "refs/heads/", 11))
@@ -111,7 +111,7 @@ static const char* get_rev_name(struct object *o)
struct rev_name *n;
struct commit *c;
- if (o->type != TYPE_COMMIT)
+ if (o->type != OBJ_COMMIT)
return "undefined";
c = (struct commit *) o;
n = c->util;
@@ -172,7 +172,7 @@ int main(int argc, char **argv)
}
o = deref_tag(parse_object(sha1), *argv, 0);
- if (!o || o->type != TYPE_COMMIT) {
+ if (!o || o->type != OBJ_COMMIT) {
fprintf(stderr, "Could not get commit for %s. Skipping.\n",
*argv);
continue;
diff --git a/object.c b/object.c
index 37277f9438..b5d8ed467d 100644
--- a/object.c
+++ b/object.c
@@ -19,7 +19,8 @@ struct object *get_indexed_object(unsigned int idx)
}
const char *type_names[] = {
- "none", "blob", "tree", "commit", "bad"
+ "none", "commit", "tree", "blob", "tag",
+ "bad type 5", "bad type 6", "delta", "bad",
};
static unsigned int hash_obj(struct object *obj, unsigned int n)
@@ -88,7 +89,7 @@ void created_object(const unsigned char *sha1, struct object *obj)
{
obj->parsed = 0;
obj->used = 0;
- obj->type = TYPE_NONE;
+ obj->type = OBJ_NONE;
obj->flags = 0;
memcpy(obj->sha1, sha1, 20);
@@ -131,7 +132,7 @@ struct object *lookup_unknown_object(const unsigned char *sha1)
if (!obj) {
union any_object *ret = xcalloc(1, sizeof(*ret));
created_object(sha1, &ret->object);
- ret->object.type = TYPE_NONE;
+ ret->object.type = OBJ_NONE;
return &ret->object;
}
return obj;
diff --git a/object.h b/object.h
index e0125e154f..733faac4cc 100644
--- a/object.h
+++ b/object.h
@@ -24,12 +24,19 @@ struct object_array {
#define TYPE_BITS 3
#define FLAG_BITS 27
-#define TYPE_NONE 0
-#define TYPE_BLOB 1
-#define TYPE_TREE 2
-#define TYPE_COMMIT 3
-#define TYPE_TAG 4
-#define TYPE_BAD 5
+/*
+ * The object type is stored in 3 bits.
+ */
+enum object_type {
+ OBJ_NONE = 0,
+ OBJ_COMMIT = 1,
+ OBJ_TREE = 2,
+ OBJ_BLOB = 3,
+ OBJ_TAG = 4,
+ /* 5/6 for future expansion */
+ OBJ_DELTA = 7,
+ OBJ_BAD,
+};
struct object {
unsigned parsed : 1;
@@ -40,14 +47,14 @@ struct object {
};
extern int track_object_refs;
-extern const char *type_names[];
+extern const char *type_names[9];
extern unsigned int get_max_object_index(void);
extern struct object *get_indexed_object(unsigned int);
static inline const char *typename(unsigned int type)
{
- return type_names[type > TYPE_TAG ? TYPE_BAD : type];
+ return type_names[type > OBJ_BAD ? OBJ_BAD : type];
}
extern struct object_refs *lookup_object_refs(struct object *);
diff --git a/pack.h b/pack.h
index 694e0c56f0..eb07b033ae 100644
--- a/pack.h
+++ b/pack.h
@@ -1,20 +1,7 @@
#ifndef PACK_H
#define PACK_H
-/*
- * The packed object type is stored in 3 bits.
- * The type value 0 is a reserved prefix if ever there is more than 7
- * object types, or any future format extensions.
- */
-enum object_type {
- OBJ_EXT = 0,
- OBJ_COMMIT = 1,
- OBJ_TREE = 2,
- OBJ_BLOB = 3,
- OBJ_TAG = 4,
- /* 5/6 for future expansion */
- OBJ_DELTA = 7,
-};
+#include "object.h"
/*
* Packed object header
diff --git a/quote.c b/quote.c
index 1910d000a5..e220dcc280 100644
--- a/quote.c
+++ b/quote.c
@@ -45,6 +45,23 @@ size_t sq_quote_buf(char *dst, size_t n, const char *src)
return len;
}
+void sq_quote_print(FILE *stream, const char *src)
+{
+ char c;
+
+ fputc('\'', stream);
+ while ((c = *src++)) {
+ if (need_bs_quote(c)) {
+ fputs("'\\", stream);
+ fputc(c, stream);
+ fputc('\'', stream);
+ } else {
+ fputc(c, stream);
+ }
+ }
+ fputc('\'', stream);
+}
+
char *sq_quote(const char *src)
{
char *buf;
diff --git a/quote.h b/quote.h
index c1ab3788e6..fc5481e78a 100644
--- a/quote.h
+++ b/quote.h
@@ -29,6 +29,7 @@
*/
extern char *sq_quote(const char *src);
+extern void sq_quote_print(FILE *stream, const char *src);
extern size_t sq_quote_buf(char *dst, size_t n, const char *src);
/* This unwraps what sq_quote() produces in place, but returns
diff --git a/revision.c b/revision.c
index 7df9089f53..874e349db8 100644
--- a/revision.c
+++ b/revision.c
@@ -135,7 +135,7 @@ static struct commit *handle_commit(struct rev_info *revs, struct object *object
/*
* Tag object? Look what it points to..
*/
- while (object->type == TYPE_TAG) {
+ while (object->type == OBJ_TAG) {
struct tag *tag = (struct tag *) object;
if (revs->tag_objects && !(flags & UNINTERESTING))
add_pending_object(revs, object, tag->tag);
@@ -148,7 +148,7 @@ static struct commit *handle_commit(struct rev_info *revs, struct object *object
* Commit object? Just return it, we'll do all the complex
* reachability crud.
*/
- if (object->type == TYPE_COMMIT) {
+ if (object->type == OBJ_COMMIT) {
struct commit *commit = (struct commit *)object;
if (parse_commit(commit) < 0)
die("unable to parse commit %s", name);
@@ -164,7 +164,7 @@ static struct commit *handle_commit(struct rev_info *revs, struct object *object
* Tree object? Either mark it uniniteresting, or add it
* to the list of objects to look at later..
*/
- if (object->type == TYPE_TREE) {
+ if (object->type == OBJ_TREE) {
struct tree *tree = (struct tree *)object;
if (!revs->tree_objects)
return NULL;
@@ -179,7 +179,7 @@ static struct commit *handle_commit(struct rev_info *revs, struct object *object
/*
* Blob object? You know the drill by now..
*/
- if (object->type == TYPE_BLOB) {
+ if (object->type == OBJ_BLOB) {
struct blob *blob = (struct blob *)object;
if (!revs->blob_objects)
return NULL;
@@ -494,11 +494,11 @@ static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
return 0;
while (1) {
it = get_reference(revs, arg, sha1, 0);
- if (it->type != TYPE_TAG)
+ if (it->type != OBJ_TAG)
break;
memcpy(sha1, ((struct tag*)it)->tagged->sha1, 20);
}
- if (it->type != TYPE_COMMIT)
+ if (it->type != OBJ_COMMIT)
return 0;
commit = (struct commit *)it;
for (parents = commit->parents; parents; parents = parents->next) {
diff --git a/send-pack.c b/send-pack.c
index 4019a4b981..10bc8bc359 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -151,12 +151,12 @@ static int ref_newer(const unsigned char *new_sha1,
* old. Otherwise we require --force.
*/
o = deref_tag(parse_object(old_sha1), NULL, 0);
- if (!o || o->type != TYPE_COMMIT)
+ if (!o || o->type != OBJ_COMMIT)
return 0;
old = (struct commit *) o;
o = deref_tag(parse_object(new_sha1), NULL, 0);
- if (!o || o->type != TYPE_COMMIT)
+ if (!o || o->type != OBJ_COMMIT)
return 0;
new = (struct commit *) o;
diff --git a/server-info.c b/server-info.c
index fdfe05a2da..7df628f2b2 100644
--- a/server-info.c
+++ b/server-info.c
@@ -12,7 +12,7 @@ static int add_info_ref(const char *path, const unsigned char *sha1)
struct object *o = parse_object(sha1);
fprintf(info_ref_fp, "%s %s\n", sha1_to_hex(sha1), path);
- if (o->type == TYPE_TAG) {
+ if (o->type == OBJ_TAG) {
o = deref_tag(o, path, 0);
if (o)
fprintf(info_ref_fp, "%s %s^{}\n",
diff --git a/sha1_file.c b/sha1_file.c
index 8734d501fe..e666aec502 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1331,31 +1331,29 @@ char *write_sha1_file_prepare(void *buf,
static int link_temp_to_file(const char *tmpfile, char *filename)
{
int ret;
+ char *dir;
if (!link(tmpfile, filename))
return 0;
/*
- * Try to mkdir the last path component if that failed
- * with an ENOENT.
+ * Try to mkdir the last path component if that failed.
*
* Re-try the "link()" regardless of whether the mkdir
* succeeds, since a race might mean that somebody
* else succeeded.
*/
ret = errno;
- if (ret == ENOENT) {
- char *dir = strrchr(filename, '/');
- if (dir) {
- *dir = 0;
- mkdir(filename, 0777);
- if (adjust_shared_perm(filename))
- return -2;
- *dir = '/';
- if (!link(tmpfile, filename))
- return 0;
- ret = errno;
- }
+ dir = strrchr(filename, '/');
+ if (dir) {
+ *dir = 0;
+ mkdir(filename, 0777);
+ if (adjust_shared_perm(filename))
+ return -2;
+ *dir = '/';
+ if (!link(tmpfile, filename))
+ return 0;
+ ret = errno;
}
return ret;
}
diff --git a/sha1_name.c b/sha1_name.c
index f2cbafa496..5fe8e5d4bf 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -381,13 +381,13 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
sp++; /* beginning of type name, or closing brace for empty */
if (!strncmp(commit_type, sp, 6) && sp[6] == '}')
- expected_type = TYPE_COMMIT;
+ expected_type = OBJ_COMMIT;
else if (!strncmp(tree_type, sp, 4) && sp[4] == '}')
- expected_type = TYPE_TREE;
+ expected_type = OBJ_TREE;
else if (!strncmp(blob_type, sp, 4) && sp[4] == '}')
- expected_type = TYPE_BLOB;
+ expected_type = OBJ_BLOB;
else if (sp[0] == '}')
- expected_type = TYPE_NONE;
+ expected_type = OBJ_NONE;
else
return -1;
@@ -416,9 +416,9 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
memcpy(sha1, o->sha1, 20);
return 0;
}
- if (o->type == TYPE_TAG)
+ if (o->type == OBJ_TAG)
o = ((struct tag*) o)->tagged;
- else if (o->type == TYPE_COMMIT)
+ else if (o->type == OBJ_COMMIT)
o = &(((struct commit *) o)->tree->object);
else
return error("%.*s: expected %s type, but the object dereferences to %s type",
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 36658fb17d..b24c829f0f 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -7,6 +7,9 @@ test_description='Various diff formatting options'
. ./test-lib.sh
+LF='
+'
+
test_expect_success setup '
GIT_AUTHOR_DATE="2006-06-26 00:00:00 +0000" &&
@@ -31,7 +34,7 @@ test_expect_success setup '
for i in C D; do echo $i; done >>dir/sub &&
rm -f file2 &&
git update-index --remove file0 file2 dir/sub &&
- git commit -m Second &&
+ git commit -m "Second${LF}${LF}This is the second commit." &&
GIT_AUTHOR_DATE="2006-06-26 00:02:00 +0000" &&
GIT_COMMITTER_DATE="2006-06-26 00:02:00 +0000" &&
diff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master
index 0ac9800913..3a9f78a09d 100644
--- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master
@@ -1,5 +1,5 @@
$ git diff-tree --cc --patch-with-stat --summary master
-176b998f5d647cbd77a9d8acf4531e930754d16d
+59d314ad6f356dd08601a4cd5e530381da3e3c64
dir/sub | 2 ++
file0 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master
index f6ecf76366..49f23b9215 100644
--- a/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master
+++ b/t/t4013/diff.diff-tree_--cc_--patch-with-stat_master
@@ -1,5 +1,5 @@
$ git diff-tree --cc --patch-with-stat master
-176b998f5d647cbd77a9d8acf4531e930754d16d
+59d314ad6f356dd08601a4cd5e530381da3e3c64
dir/sub | 2 ++
file0 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master b/t/t4013/diff.diff-tree_--cc_--stat_--summary_master
index 712ffd2d89..cc6eb3b3d5 100644
--- a/t/t4013/diff.diff-tree_--cc_--stat_--summary_master
+++ b/t/t4013/diff.diff-tree_--cc_--stat_--summary_master
@@ -1,5 +1,5 @@
$ git diff-tree --cc --stat --summary master
-176b998f5d647cbd77a9d8acf4531e930754d16d
+59d314ad6f356dd08601a4cd5e530381da3e3c64
dir/sub | 2 ++
file0 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/t/t4013/diff.diff-tree_--cc_--stat_master b/t/t4013/diff.diff-tree_--cc_--stat_master
index 8d5bdc985a..fae7f33255 100644
--- a/t/t4013/diff.diff-tree_--cc_--stat_master
+++ b/t/t4013/diff.diff-tree_--cc_--stat_master
@@ -1,5 +1,5 @@
$ git diff-tree --cc --stat master
-176b998f5d647cbd77a9d8acf4531e930754d16d
+59d314ad6f356dd08601a4cd5e530381da3e3c64
dir/sub | 2 ++
file0 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/t/t4013/diff.diff-tree_--cc_master b/t/t4013/diff.diff-tree_--cc_master
index e57d943bdc..5ecb4e14ae 100644
--- a/t/t4013/diff.diff-tree_--cc_master
+++ b/t/t4013/diff.diff-tree_--cc_master
@@ -1,5 +1,5 @@
$ git diff-tree --cc master
-176b998f5d647cbd77a9d8acf4531e930754d16d
+59d314ad6f356dd08601a4cd5e530381da3e3c64
diff --cc dir/sub
index cead32e,7289e35..992913c
--- a/dir/sub
diff --git a/t/t4013/diff.diff-tree_-c_--abbrev_master b/t/t4013/diff.diff-tree_-c_--abbrev_master
index 39d511a7cf..b8e4aa2530 100644
--- a/t/t4013/diff.diff-tree_-c_--abbrev_master
+++ b/t/t4013/diff.diff-tree_-c_--abbrev_master
@@ -1,5 +1,5 @@
$ git diff-tree -c --abbrev master
-176b998f5d647cbd77a9d8acf4531e930754d16d
+59d314ad6f356dd08601a4cd5e530381da3e3c64
::100644 100644 100644 cead32e... 7289e35... 992913c... MM dir/sub
::100644 100644 100644 b414108... f4615da... 10a8a9f... MM file0
$
diff --git a/t/t4013/diff.diff-tree_-c_--stat_--summary_master b/t/t4013/diff.diff-tree_-c_--stat_--summary_master
index 2d239feb5d..ac9f641fb4 100644
--- a/t/t4013/diff.diff-tree_-c_--stat_--summary_master
+++ b/t/t4013/diff.diff-tree_-c_--stat_--summary_master
@@ -1,5 +1,5 @@
$ git diff-tree -c --stat --summary master
-176b998f5d647cbd77a9d8acf4531e930754d16d
+59d314ad6f356dd08601a4cd5e530381da3e3c64
dir/sub | 2 ++
file0 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/t/t4013/diff.diff-tree_-c_--stat_master b/t/t4013/diff.diff-tree_-c_--stat_master
index 226300b93c..c2fe6a98c5 100644
--- a/t/t4013/diff.diff-tree_-c_--stat_master
+++ b/t/t4013/diff.diff-tree_-c_--stat_master
@@ -1,5 +1,5 @@
$ git diff-tree -c --stat master
-176b998f5d647cbd77a9d8acf4531e930754d16d
+59d314ad6f356dd08601a4cd5e530381da3e3c64
dir/sub | 2 ++
file0 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/t/t4013/diff.diff-tree_-c_master b/t/t4013/diff.diff-tree_-c_master
index c258efe222..e2d2bb2611 100644
--- a/t/t4013/diff.diff-tree_-c_master
+++ b/t/t4013/diff.diff-tree_-c_master
@@ -1,5 +1,5 @@
$ git diff-tree -c master
-176b998f5d647cbd77a9d8acf4531e930754d16d
+59d314ad6f356dd08601a4cd5e530381da3e3c64
::100644 100644 100644 cead32e925b1420c84c14cbf7cf755e7e45af8ad 7289e35bff32727c08dda207511bec138fdb9ea5 992913c5aa0a5476d10c49ed0f21fc0c6d1aedf3 MM dir/sub
::100644 100644 100644 b414108e81e5091fe0974a1858b4d0d22b107f70 f4615da674c09df322d6ba8d6b21ecfb1b1ba510 10a8a9f3657f91a156b9f0184ed79a20adef9f7f MM file0
$
diff --git a/t/t4013/diff.diff-tree_-p_-m_master b/t/t4013/diff.diff-tree_-p_-m_master
index 1be721560a..b60bea039d 100644
--- a/t/t4013/diff.diff-tree_-p_-m_master
+++ b/t/t4013/diff.diff-tree_-p_-m_master
@@ -1,5 +1,5 @@
$ git diff-tree -p -m master
-176b998f5d647cbd77a9d8acf4531e930754d16d
+59d314ad6f356dd08601a4cd5e530381da3e3c64
diff --git a/dir/sub b/dir/sub
index cead32e..992913c 100644
--- a/dir/sub
@@ -21,7 +21,7 @@ index b414108..10a8a9f 100644
+A
+B
+C
-176b998f5d647cbd77a9d8acf4531e930754d16d
+59d314ad6f356dd08601a4cd5e530381da3e3c64
diff --git a/dir/sub b/dir/sub
index 7289e35..992913c 100644
--- a/dir/sub
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master b/t/t4013/diff.format-patch_--attach_--stdout_initial..master
index a89bbbbcfb..b4745e1001 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master
@@ -1,5 +1,5 @@
$ git format-patch --attach --stdout initial..master
-From 7952a93e09bf565b5592766a438b40cd81f4846f Mon Sep 17 00:00:00 2001
+From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
Subject: [PATCH] Second
@@ -11,6 +11,9 @@ This is a multi-part message in MIME format.
--------------g-i-t--v-e-r-s-i-o-n
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
+
+
+This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
@@ -18,10 +21,10 @@ Content-Transfer-Encoding: 8bit
3 files changed, 5 insertions(+), 3 deletions(-)
--------------g-i-t--v-e-r-s-i-o-n
Content-Type: text/x-patch;
- name="7952a93e09bf565b5592766a438b40cd81f4846f.diff"
+ name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline;
- filename="7952a93e09bf565b5592766a438b40cd81f4846f.diff"
+ filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
@@ -57,7 +60,7 @@ index 01e79c3..0000000
-From 889b315013ef9f2e2f90aa0b054b267c8a557847 Mon Sep 17 00:00:00 2001
+From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
Subject: [PATCH] Third
@@ -69,16 +72,17 @@ This is a multi-part message in MIME format.
--------------g-i-t--v-e-r-s-i-o-n
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
+
---
dir/sub | 2 ++
file1 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
--------------g-i-t--v-e-r-s-i-o-n
Content-Type: text/x-patch;
- name="889b315013ef9f2e2f90aa0b054b267c8a557847.diff"
+ name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline;
- filename="889b315013ef9f2e2f90aa0b054b267c8a557847.diff"
+ filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
diff --git a/dir/sub b/dir/sub
index 8422d40..cead32e 100644
@@ -116,6 +120,7 @@ This is a multi-part message in MIME format.
--------------g-i-t--v-e-r-s-i-o-n
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
+
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
index 4de9091a40..a9d1cd368b 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..master^
@@ -1,5 +1,5 @@
$ git format-patch --attach --stdout initial..master^
-From 7952a93e09bf565b5592766a438b40cd81f4846f Mon Sep 17 00:00:00 2001
+From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
Subject: [PATCH] Second
@@ -11,6 +11,9 @@ This is a multi-part message in MIME format.
--------------g-i-t--v-e-r-s-i-o-n
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
+
+
+This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
@@ -18,10 +21,10 @@ Content-Transfer-Encoding: 8bit
3 files changed, 5 insertions(+), 3 deletions(-)
--------------g-i-t--v-e-r-s-i-o-n
Content-Type: text/x-patch;
- name="7952a93e09bf565b5592766a438b40cd81f4846f.diff"
+ name="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline;
- filename="7952a93e09bf565b5592766a438b40cd81f4846f.diff"
+ filename="1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44.diff"
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
@@ -57,7 +60,7 @@ index 01e79c3..0000000
-From 889b315013ef9f2e2f90aa0b054b267c8a557847 Mon Sep 17 00:00:00 2001
+From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
Subject: [PATCH] Third
@@ -69,16 +72,17 @@ This is a multi-part message in MIME format.
--------------g-i-t--v-e-r-s-i-o-n
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
+
---
dir/sub | 2 ++
file1 | 3 +++
2 files changed, 5 insertions(+), 0 deletions(-)
--------------g-i-t--v-e-r-s-i-o-n
Content-Type: text/x-patch;
- name="889b315013ef9f2e2f90aa0b054b267c8a557847.diff"
+ name="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline;
- filename="889b315013ef9f2e2f90aa0b054b267c8a557847.diff"
+ filename="9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0.diff"
diff --git a/dir/sub b/dir/sub
index 8422d40..cead32e 100644
diff --git a/t/t4013/diff.format-patch_--attach_--stdout_initial..side b/t/t4013/diff.format-patch_--attach_--stdout_initial..side
index 3769fa6daf..57b9d0bdc1 100644
--- a/t/t4013/diff.format-patch_--attach_--stdout_initial..side
+++ b/t/t4013/diff.format-patch_--attach_--stdout_initial..side
@@ -11,6 +11,7 @@ This is a multi-part message in MIME format.
--------------g-i-t--v-e-r-s-i-o-n
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
+
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.format-patch_--stdout_initial..master b/t/t4013/diff.format-patch_--stdout_initial..master
index b7b4e7ca91..c33302e92f 100644
--- a/t/t4013/diff.format-patch_--stdout_initial..master
+++ b/t/t4013/diff.format-patch_--stdout_initial..master
@@ -1,8 +1,10 @@
$ git format-patch --stdout initial..master
-From 7952a93e09bf565b5592766a438b40cd81f4846f Mon Sep 17 00:00:00 2001
+From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
Subject: [PATCH] Second
+
+This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
@@ -42,10 +44,11 @@ index 01e79c3..0000000
g-i-t--v-e-r-s-i-o-n
-From 889b315013ef9f2e2f90aa0b054b267c8a557847 Mon Sep 17 00:00:00 2001
+From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
Subject: [PATCH] Third
+
---
dir/sub | 2 ++
file1 | 3 +++
@@ -78,6 +81,7 @@ From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:03:00 +0000
Subject: [PATCH] Side
+
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.format-patch_--stdout_initial..master^ b/t/t4013/diff.format-patch_--stdout_initial..master^
index e56dd98df3..03d0f9693c 100644
--- a/t/t4013/diff.format-patch_--stdout_initial..master^
+++ b/t/t4013/diff.format-patch_--stdout_initial..master^
@@ -1,8 +1,10 @@
$ git format-patch --stdout initial..master^
-From 7952a93e09bf565b5592766a438b40cd81f4846f Mon Sep 17 00:00:00 2001
+From 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:01:00 +0000
Subject: [PATCH] Second
+
+This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
@@ -42,10 +44,11 @@ index 01e79c3..0000000
g-i-t--v-e-r-s-i-o-n
-From 889b315013ef9f2e2f90aa0b054b267c8a557847 Mon Sep 17 00:00:00 2001
+From 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0 Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:02:00 +0000
Subject: [PATCH] Third
+
---
dir/sub | 2 ++
file1 | 3 +++
diff --git a/t/t4013/diff.format-patch_--stdout_initial..side b/t/t4013/diff.format-patch_--stdout_initial..side
index e7ddbf4814..d10a46523b 100644
--- a/t/t4013/diff.format-patch_--stdout_initial..side
+++ b/t/t4013/diff.format-patch_--stdout_initial..side
@@ -3,6 +3,7 @@ From c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a Mon Sep 17 00:00:00 2001
From: A U Thor <author@example.com>
Date: Mon, 26 Jun 2006 00:03:00 +0000
Subject: [PATCH] Side
+
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
index cc5537697d..3ceb8e73c5 100644
--- a/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_
@@ -1,6 +1,6 @@
$ git log --patch-with-stat --summary master -- dir/
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -25,7 +25,7 @@ index 35d242b..7289e35 100644
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -45,11 +45,13 @@ index 8422d40..cead32e 100644
+E
+F
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/t/t4013/diff.log_--patch-with-stat_master b/t/t4013/diff.log_--patch-with-stat_master
index b97969dc98..43d77761f9 100644
--- a/t/t4013/diff.log_--patch-with-stat_master
+++ b/t/t4013/diff.log_--patch-with-stat_master
@@ -1,6 +1,6 @@
$ git log --patch-with-stat master
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -48,7 +48,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -78,11 +78,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.log_--patch-with-stat_master_--_dir_ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_
index 71a6d0f853..5187a26816 100644
--- a/t/t4013/diff.log_--patch-with-stat_master_--_dir_
+++ b/t/t4013/diff.log_--patch-with-stat_master_--_dir_
@@ -1,6 +1,6 @@
$ git log --patch-with-stat master -- dir/
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -25,7 +25,7 @@ index 35d242b..7289e35 100644
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -45,11 +45,13 @@ index 8422d40..cead32e 100644
+E
+F
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
index b652c6a823..c9640976a8 100644
--- a/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master
@@ -1,6 +1,6 @@
$ git log --root --cc --patch-with-stat --summary master
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -81,7 +81,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -112,11 +112,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
index b24a504759..ad050af55f 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_--summary_master
@@ -1,6 +1,6 @@
$ git log --root --patch-with-stat --summary master
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -49,7 +49,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -80,11 +80,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.log_--root_--patch-with-stat_master b/t/t4013/diff.log_--root_--patch-with-stat_master
index 1e9bdc4c1c..628c6c03bc 100644
--- a/t/t4013/diff.log_--root_--patch-with-stat_master
+++ b/t/t4013/diff.log_--root_--patch-with-stat_master
@@ -1,6 +1,6 @@
$ git log --root --patch-with-stat master
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -48,7 +48,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -78,11 +78,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
index 3a155d288c..5d4e0f13b5 100644
--- a/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master
@@ -1,6 +1,6 @@
$ git log --root -c --patch-with-stat --summary master
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -81,7 +81,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -112,11 +112,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.log_--root_-p_master b/t/t4013/diff.log_--root_-p_master
index 2296986ad1..217a2eb203 100644
--- a/t/t4013/diff.log_--root_-p_master
+++ b/t/t4013/diff.log_--root_-p_master
@@ -1,6 +1,6 @@
$ git log --root -p master
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -43,7 +43,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -69,11 +69,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
diff --git a/t/t4013/diff.log_--root_master b/t/t4013/diff.log_--root_master
index 7554a468d1..e17ccfc234 100644
--- a/t/t4013/diff.log_--root_master
+++ b/t/t4013/diff.log_--root_master
@@ -1,6 +1,6 @@
$ git log --root master
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -12,17 +12,19 @@ Date: Mon Jun 26 00:03:00 2006 +0000
Side
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
Third
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
commit 444ac553ac7612cc88969031b02b3767fb8a353a
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.log_-SF_-p_master b/t/t4013/diff.log_-SF_-p_master
index db2264c6e9..5e32438972 100644
--- a/t/t4013/diff.log_-SF_-p_master
+++ b/t/t4013/diff.log_-SF_-p_master
@@ -1,5 +1,5 @@
$ git log -SF -p master
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-SF_master b/t/t4013/diff.log_-SF_master
index f307b4d2a8..6162ed2018 100644
--- a/t/t4013/diff.log_-SF_master
+++ b/t/t4013/diff.log_-SF_master
@@ -1,5 +1,5 @@
$ git log -SF master
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.log_-p_master b/t/t4013/diff.log_-p_master
index e82a72f6f8..f8fefef2c3 100644
--- a/t/t4013/diff.log_-p_master
+++ b/t/t4013/diff.log_-p_master
@@ -1,6 +1,6 @@
$ git log -p master
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -43,7 +43,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -69,11 +69,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
diff --git a/t/t4013/diff.log_master b/t/t4013/diff.log_master
index 7b86ed1f5d..e9d9e7b40a 100644
--- a/t/t4013/diff.log_master
+++ b/t/t4013/diff.log_master
@@ -1,6 +1,6 @@
$ git log master
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -12,17 +12,19 @@ Date: Mon Jun 26 00:03:00 2006 +0000
Side
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
Third
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
commit 444ac553ac7612cc88969031b02b3767fb8a353a
Author: A U Thor <author@example.com>
diff --git a/t/t4013/diff.show_master b/t/t4013/diff.show_master
index 3772a87e13..9e6e1f2710 100644
--- a/t/t4013/diff.show_master
+++ b/t/t4013/diff.show_master
@@ -1,6 +1,6 @@
$ git show master
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_
index 054513f312..6a467cccc1 100644
--- a/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_
+++ b/t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_
@@ -18,7 +18,7 @@ index 35d242b..7289e35 100644
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -38,11 +38,13 @@ index 8422d40..cead32e 100644
+E
+F
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master b/t/t4013/diff.whatchanged_--patch-with-stat_master
index a89b573f45..1e1bbe1963 100644
--- a/t/t4013/diff.whatchanged_--patch-with-stat_master
+++ b/t/t4013/diff.whatchanged_--patch-with-stat_master
@@ -41,7 +41,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -71,11 +71,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ b/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_
index b6d9752164..13789f169b 100644
--- a/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_
+++ b/t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_
@@ -18,7 +18,7 @@ index 35d242b..7289e35 100644
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -38,11 +38,13 @@ index 8422d40..cead32e 100644
+E
+F
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
index e9e17cdafb..5facf2543d 100644
--- a/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master
@@ -1,6 +1,6 @@
$ git whatchanged --root --cc --patch-with-stat --summary master
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -81,7 +81,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -112,11 +112,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master
index f707bfa3a1..0291153587 100644
--- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master
@@ -42,7 +42,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -73,11 +73,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master b/t/t4013/diff.whatchanged_--root_--patch-with-stat_master
index 61aca41711..9b0349cd55 100644
--- a/t/t4013/diff.whatchanged_--root_--patch-with-stat_master
+++ b/t/t4013/diff.whatchanged_--root_--patch-with-stat_master
@@ -41,7 +41,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -71,11 +71,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
index 596765e804..10f6767e49 100644
--- a/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
+++ b/t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master
@@ -1,6 +1,6 @@
$ git whatchanged --root -c --patch-with-stat --summary master
-commit 176b998f5d647cbd77a9d8acf4531e930754d16d
-Merge: 889b315... c7a2ab9...
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494... c7a2ab9...
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:04:00 2006 +0000
@@ -81,7 +81,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -112,11 +112,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
---
dir/sub | 2 ++
file0 | 3 +++
diff --git a/t/t4013/diff.whatchanged_--root_-p_master b/t/t4013/diff.whatchanged_--root_-p_master
index b4cd05e576..ebf1f0661e 100644
--- a/t/t4013/diff.whatchanged_--root_-p_master
+++ b/t/t4013/diff.whatchanged_--root_-p_master
@@ -36,7 +36,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -62,11 +62,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
diff --git a/t/t4013/diff.whatchanged_--root_master b/t/t4013/diff.whatchanged_--root_master
index 011a22178f..a405cb6138 100644
--- a/t/t4013/diff.whatchanged_--root_master
+++ b/t/t4013/diff.whatchanged_--root_master
@@ -9,7 +9,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000
:100644 100644 01e79c3... f4615da... M file0
:000000 100644 0000000... 7289e35... A file3
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -18,11 +18,13 @@ Date: Mon Jun 26 00:02:00 2006 +0000
:100644 100644 8422d40... cead32e... M dir/sub
:000000 100644 0000000... b1e6722... A file1
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
:100644 100644 35d242b... 8422d40... M dir/sub
:100644 100644 01e79c3... b414108... M file0
diff --git a/t/t4013/diff.whatchanged_-SF_-p_master b/t/t4013/diff.whatchanged_-SF_-p_master
index 6a76f4e604..f39da84822 100644
--- a/t/t4013/diff.whatchanged_-SF_-p_master
+++ b/t/t4013/diff.whatchanged_-SF_-p_master
@@ -1,5 +1,5 @@
$ git whatchanged -SF -p master
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_-SF_master b/t/t4013/diff.whatchanged_-SF_master
index a4fe6f8a39..0499321d0e 100644
--- a/t/t4013/diff.whatchanged_-SF_master
+++ b/t/t4013/diff.whatchanged_-SF_master
@@ -1,5 +1,5 @@
$ git whatchanged -SF master
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
diff --git a/t/t4013/diff.whatchanged_-p_master b/t/t4013/diff.whatchanged_-p_master
index f9a4456725..f18d43209c 100644
--- a/t/t4013/diff.whatchanged_-p_master
+++ b/t/t4013/diff.whatchanged_-p_master
@@ -36,7 +36,7 @@ index 0000000..7289e35
+1
+2
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -62,11 +62,13 @@ index 0000000..b1e6722
+B
+C
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
diff --git a/dir/sub b/dir/sub
index 35d242b..8422d40 100644
diff --git a/t/t4013/diff.whatchanged_master b/t/t4013/diff.whatchanged_master
index c22416c006..cd3bcc2c72 100644
--- a/t/t4013/diff.whatchanged_master
+++ b/t/t4013/diff.whatchanged_master
@@ -9,7 +9,7 @@ Date: Mon Jun 26 00:03:00 2006 +0000
:100644 100644 01e79c3... f4615da... M file0
:000000 100644 0000000... 7289e35... A file3
-commit 889b315013ef9f2e2f90aa0b054b267c8a557847
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:02:00 2006 +0000
@@ -18,11 +18,13 @@ Date: Mon Jun 26 00:02:00 2006 +0000
:100644 100644 8422d40... cead32e... M dir/sub
:000000 100644 0000000... b1e6722... A file1
-commit 7952a93e09bf565b5592766a438b40cd81f4846f
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
Author: A U Thor <author@example.com>
Date: Mon Jun 26 00:01:00 2006 +0000
Second
+
+ This is the second commit.
:100644 100644 35d242b... 8422d40... M dir/sub
:100644 100644 01e79c3... b414108... M file0
diff --git a/t/t6010-merge-base.sh b/t/t6010-merge-base.sh
index 1dce123aec..b15920b852 100755
--- a/t/t6010-merge-base.sh
+++ b/t/t6010-merge-base.sh
@@ -44,6 +44,43 @@ A=$(doit 1 A $B)
G=$(doit 7 G $B $E)
H=$(doit 8 H $A $F)
+# Setup for second test to demonstrate that relying on timestamps in a
+# distributed SCM to provide a _consistent_ partial ordering of commits
+# leads to insanity.
+#
+# Relative
+# Structure timestamps
+#
+# PL PR +4 +4
+# / \/ \ / \/ \
+# L2 C2 R2 +3 -1 +3
+# | | | | | |
+# L1 C1 R1 +2 -2 +2
+# | | | | | |
+# L0 C0 R0 +1 -3 +1
+# \ | / \ | /
+# S 0
+#
+# The left and right chains of commits can be of any length and complexity as
+# long as all of the timestamps are greater than that of S.
+
+S=$(doit 0 S)
+
+C0=$(doit -3 C0 $S)
+C1=$(doit -2 C1 $C0)
+C2=$(doit -1 C2 $C1)
+
+L0=$(doit 1 L0 $S)
+L1=$(doit 2 L1 $L0)
+L2=$(doit 3 L2 $L1)
+
+R0=$(doit 1 R0 $S)
+R1=$(doit 2 R1 $R0)
+R2=$(doit 3 R2 $R1)
+
+PL=$(doit 4 PL $L2 $C2)
+PR=$(doit 4 PR $C2 $R2)
+
test_expect_success 'compute merge-base (single)' \
'MB=$(git-merge-base G H) &&
expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/B"'
@@ -56,4 +93,12 @@ test_expect_success 'compute merge-base with show-branch' \
'MB=$(git-show-branch --merge-base G H) &&
expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/B"'
+test_expect_success 'compute merge-base (single)' \
+ 'MB=$(git-merge-base PL PR) &&
+ expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/C2"'
+
+test_expect_success 'compute merge-base (all)' \
+ 'MB=$(git-merge-base --all PL PR) &&
+ expr "$(git-name-rev "$MB")" : "[0-9a-f]* tags/C2"'
+
test_done
diff --git a/t/test-lib.sh b/t/test-lib.sh
index b0d7990a66..470a909891 100755
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -28,6 +28,7 @@ unset GIT_DIR
unset GIT_EXTERNAL_DIFF
unset GIT_INDEX_FILE
unset GIT_OBJECT_DIRECTORY
+unset GIT_TRACE
unset SHA1_FILE_DIRECTORIES
unset SHA1_FILE_DIRECTORY
export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
diff --git a/tag.c b/tag.c
index 74d0dabe5d..864ac1bb60 100644
--- a/tag.c
+++ b/tag.c
@@ -5,7 +5,7 @@ const char *tag_type = "tag";
struct object *deref_tag(struct object *o, const char *warn, int warnlen)
{
- while (o && o->type == TYPE_TAG)
+ while (o && o->type == OBJ_TAG)
o = parse_object(((struct tag *)o)->tagged->sha1);
if (!o && warn) {
if (!warnlen)
@@ -21,12 +21,12 @@ struct tag *lookup_tag(const unsigned char *sha1)
if (!obj) {
struct tag *ret = alloc_tag_node();
created_object(sha1, &ret->object);
- ret->object.type = TYPE_TAG;
+ ret->object.type = OBJ_TAG;
return ret;
}
if (!obj->type)
- obj->type = TYPE_TAG;
- if (obj->type != TYPE_TAG) {
+ obj->type = OBJ_TAG;
+ if (obj->type != OBJ_TAG) {
error("Object %s is a %s, not a tree",
sha1_to_hex(sha1), typename(obj->type));
return NULL;
diff --git a/tree.c b/tree.c
index 10236555cc..a6032e35ec 100644
--- a/tree.c
+++ b/tree.c
@@ -131,12 +131,12 @@ struct tree *lookup_tree(const unsigned char *sha1)
if (!obj) {
struct tree *ret = alloc_tree_node();
created_object(sha1, &ret->object);
- ret->object.type = TYPE_TREE;
+ ret->object.type = OBJ_TREE;
return ret;
}
if (!obj->type)
- obj->type = TYPE_TREE;
- if (obj->type != TYPE_TREE) {
+ obj->type = OBJ_TREE;
+ if (obj->type != OBJ_TREE) {
error("Object %s is a %s, not a tree",
sha1_to_hex(sha1), typename(obj->type));
return NULL;
@@ -216,11 +216,11 @@ struct tree *parse_tree_indirect(const unsigned char *sha1)
do {
if (!obj)
return NULL;
- if (obj->type == TYPE_TREE)
+ if (obj->type == OBJ_TREE)
return (struct tree *) obj;
- else if (obj->type == TYPE_COMMIT)
+ else if (obj->type == OBJ_COMMIT)
obj = &(((struct commit *) obj)->tree->object);
- else if (obj->type == TYPE_TAG)
+ else if (obj->type == OBJ_TAG)
obj = ((struct tag *) obj)->tagged;
else
return NULL;
diff --git a/upload-pack.c b/upload-pack.c
index b18eb9ba0d..f6f5a7e3db 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -51,6 +51,10 @@ static ssize_t send_client_data(int fd, const char *data, ssize_t sz)
if (fd == 3)
/* emergency quit */
fd = 2;
+ if (fd == 2) {
+ xwrite(fd, data, sz);
+ return sz;
+ }
return safe_write(fd, data, sz);
}
p = data;
@@ -326,7 +330,7 @@ static int got_sha1(char *hex, unsigned char *sha1)
o = parse_object(sha1);
if (!o)
die("oops (%s)", sha1_to_hex(sha1));
- if (o->type == TYPE_COMMIT) {
+ if (o->type == OBJ_COMMIT) {
struct commit_list *parents;
if (o->flags & THEY_HAVE)
return 0;
@@ -457,7 +461,7 @@ static int send_ref(const char *refname, const unsigned char *sha1)
o->flags |= OUR_REF;
nr_our_refs++;
}
- if (o->type == TYPE_TAG) {
+ if (o->type == OBJ_TAG) {
o = deref_tag(o, refname, 0);
packet_write(1, "%s %s^{}\n", sha1_to_hex(o->sha1), refname);
}
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 2ce10b4c0d..c9f817818a 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -39,6 +39,7 @@ extern "C" {
#define XDL_PATCH_IGNOREBSPACE (1 << 8)
#define XDL_EMIT_FUNCNAMES (1 << 0)
+#define XDL_EMIT_COMMON (1 << 1)
#define XDL_MMB_READONLY (1 << 0)
diff --git a/xdiff/xemit.c b/xdiff/xemit.c
index ad5bfb1910..714c563547 100644
--- a/xdiff/xemit.c
+++ b/xdiff/xemit.c
@@ -100,6 +100,21 @@ static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) {
}
+int xdl_emit_common(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
+ xdemitconf_t const *xecfg) {
+ xdfile_t *xdf = &xe->xdf1;
+ const char *rchg = xdf->rchg;
+ long ix;
+
+ for (ix = 0; ix < xdf->nrec; ix++) {
+ if (rchg[ix])
+ continue;
+ if (xdl_emit_record(xdf, ix, "", ecb))
+ return -1;
+ }
+ return 0;
+}
+
int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
xdemitconf_t const *xecfg) {
long s1, s2, e1, e2, lctx;
@@ -107,6 +122,9 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
char funcbuf[40];
long funclen = 0;
+ if (xecfg->flags & XDL_EMIT_COMMON)
+ return xdl_emit_common(xe, xscr, ecb, xecfg);
+
for (xch = xche = xscr; xch; xch = xche->next) {
xche = xdl_get_hunk(xch, xecfg);