summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--Documentation/Makefile2
-rw-r--r--Documentation/git-build-rev-cache.txt38
-rw-r--r--Documentation/git-fetch.txt6
-rw-r--r--Documentation/git-rev-list.txt7
-rw-r--r--Documentation/git-show-rev-cache.txt37
-rw-r--r--Documentation/git-update-server-info.txt2
-rw-r--r--Documentation/git.txt6
-rw-r--r--Documentation/pull-fetch-param.txt11
-rw-r--r--Documentation/repository-layout.txt7
-rw-r--r--Makefile24
-rw-r--r--build-rev-cache.c56
-rwxr-xr-xcmd-rename.sh6
-rw-r--r--commit.c4
-rw-r--r--commit.h1
-rw-r--r--convert-objects.c1
-rw-r--r--debian/control4
-rwxr-xr-xdebian/rules2
-rw-r--r--diff-tree.c1
-rw-r--r--diff.c24
-rw-r--r--diffcore-break.c4
-rw-r--r--diffcore-rename.c56
-rw-r--r--diffcore.h2
-rw-r--r--fetch.c100
-rwxr-xr-xgit-bisect.sh2
-rwxr-xr-xgit-branch.sh60
-rwxr-xr-xgit-checkout.sh3
-rwxr-xr-xgit-clone.sh28
-rw-r--r--git-core.spec.in29
-rwxr-xr-xgit-fetch.sh24
-rwxr-xr-xgit-parse-remote.sh21
-rwxr-xr-xgit-pull.sh6
-rwxr-xr-xgit-repack.sh10
-rwxr-xr-xgit-shortlog.perl2
-rw-r--r--http-fetch.c177
-rw-r--r--ident.c2
-rw-r--r--object.c13
-rw-r--r--object.h1
-rw-r--r--rev-cache.c318
-rw-r--r--rev-cache.h29
-rw-r--r--rev-list.c59
-rw-r--r--rsh.c105
-rw-r--r--server-info.c67
-rw-r--r--show-rev-cache.c18
-rw-r--r--ssh-fetch.c15
-rw-r--r--ssh-pull.c4
-rw-r--r--ssh-push.c4
-rw-r--r--ssh-upload.c16
-rwxr-xr-xt/t1001-read-tree-m-2way.sh2
49 files changed, 640 insertions, 781 deletions
diff --git a/.gitignore b/.gitignore
index 31c03f4..0fd59b9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,7 +6,6 @@ git-applypatch
git-archimport
git-bisect
git-branch
-git-build-rev-cache
git-cat-file
git-checkout
git-checkout-index
@@ -73,13 +72,15 @@ git-rev-list
git-rev-parse
git-rev-tree
git-revert
+git-send-email
git-send-pack
git-sh-setup
git-shortlog
git-show-branch
git-show-index
-git-show-rev-cache
git-ssh-fetch
+git-ssh-pull
+git-ssh-push
git-ssh-upload
git-status
git-stripspace
diff --git a/Documentation/Makefile b/Documentation/Makefile
index b81a6a2..37b7fcb 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -45,7 +45,7 @@ man1: $(DOC_MAN1)
man7: $(DOC_MAN7)
install:
- $(INSTALL) -m755 -d $(DESTDIR)/$(man1) $(DESTDIR)/$(man7)
+ $(INSTALL) -d -m755 $(DESTDIR)/$(man1) $(DESTDIR)/$(man7)
$(INSTALL) $(DOC_MAN1) $(DESTDIR)/$(man1)
$(INSTALL) $(DOC_MAN7) $(DESTDIR)/$(man7)
diff --git a/Documentation/git-build-rev-cache.txt b/Documentation/git-build-rev-cache.txt
deleted file mode 100644
index 1dbad77..0000000
--- a/Documentation/git-build-rev-cache.txt
+++ /dev/null
@@ -1,38 +0,0 @@
-git-build-rev-cache(1)
-======================
-
-NAME
-----
-git-build-rev-cache - Create or update a rev-cache file.
-
-SYNOPSIS
---------
-'git-build-rev-cache' [-v] <rev-cache-file> < list-of-heads
-
-DESCRIPTION
------------
-Creates or updates a file that describes the commit ancestry reachable
-from the list-of-head read from stdin. This file is in an append-only
-binary format to make the server side friendly to rsync mirroring
-scheme, and can be read by the git-show-rev-cache command.
-
-OPTIONS
--------
--v::
- Verbose.
-
-<rev-cache-file>::
- The rev-cache to operate on.
-
-Author
-------
-Written by Junio C Hamano <junkio@cox.net>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-GIT
----
-Part of the link:git.html[git] suite
-
diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt
index 017f646..8c1cc07 100644
--- a/Documentation/git-fetch.txt
+++ b/Documentation/git-fetch.txt
@@ -26,6 +26,12 @@ OPTIONS
-------
include::pull-fetch-param.txt[]
+-u, \--update-head-ok::
+ By default 'git-fetch' refuses to update the head which
+ corresponds to the current branch. This flag disables the
+ check. Note that fetching into the current branch will not
+ update the index and working directory, so use it with care.
+
Author
------
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index 35fecf3..32c06a1 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -32,8 +32,11 @@ I have the commit object 'bar', but not 'foo'".
The *--bisect* flag limits output to the one commit object which is
roughly halfway between the included and excluded commits. Thus,
-if "git-rev-list --bisect foo ^bar ^baz" outputs 'midpoint', the output
-of "git-rev-list foo ^midpoint" and "git-rev-list midpoint ^bar ^baz"
+if 'git-rev-list --bisect foo ^bar
+^baz' outputs 'midpoint', the output
+of 'git-rev-list foo ^midpoint' and 'git-rev-list midpoint
+^bar
+^baz'
would be of roughly the same length. Finding the change which introduces
a regression is thus reduced to a binary search: repeatedly generate and
test new 'midpoint's until the commit chain is of length one.
diff --git a/Documentation/git-show-rev-cache.txt b/Documentation/git-show-rev-cache.txt
deleted file mode 100644
index 104ecb7..0000000
--- a/Documentation/git-show-rev-cache.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-git-show-rev-cache(1)
-=====================
-
-NAME
-----
-git-show-rev-cache - Show the contents of a rev-cache file.
-
-SYNOPSIS
---------
-'git-show-rev-cache' <rev-cache-file>
-
-DESCRIPTION
------------
-Show the contents of <rev-cache-file>.
-
-A rev-cache file describes the commit ancestry reachable from references
-supplied as input to get-build-rev-cache. This file is in an
-append-only binary format to make the server side friendly to rsync
-mirroring scheme.
-
-OPTIONS
--------
-<rev-cache-file>::
- Rev-cache file to display.
-
-Author
-------
-Written by Junio C Hamano <junkio@cox.net>
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-GIT
----
-Part of the link:git.html[git] suite
-
diff --git a/Documentation/git-update-server-info.txt b/Documentation/git-update-server-info.txt
index 74c4364..39222c3 100644
--- a/Documentation/git-update-server-info.txt
+++ b/Documentation/git-update-server-info.txt
@@ -38,8 +38,6 @@ of what they are for:
* info/refs
-* info/rev-cache
-
BUGS
----
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 31dd474..bec562e 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -359,9 +359,6 @@ link:git-tag.html[git-tag]::
Interrogators:
-link:git-build-rev-cache.html[git-build-rev-cache]::
- Create or update a rev-cache file.
-
link:git-cherry.html[git-cherry]::
Find commits not merged upstream.
@@ -402,9 +399,6 @@ link:git-send-email.html[git-send-email]::
Send patch e-mails out of "format-patch --mbox" output.
Previously this command was known as git-send-email-script.
-link:git-show-rev-cache.html[git-show-rev-cache]::
- Show the contents of a rev-cache file.
-
link:git-stripspace.html[git-stripspace]::
Filter out empty lines.
diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt
index 8f6b68c..8642182 100644
--- a/Documentation/pull-fetch-param.txt
+++ b/Documentation/pull-fetch-param.txt
@@ -80,3 +80,14 @@
<ref>: when pulling/fetching, and <ref>:<ref> when
pushing. That is, do not store it locally if
fetching, and update the same name if pushing.
+
+-a, \--append::
+ Append ref names and object names of fetched refs to the
+ existing contents of $GIT_DIR/FETCH_HEAD. Without this
+ option old data in $GIT_DIR/FETCH_HEAD will be overwritten.
+
+-f, \--force::
+ Usually, the command refuses to update a local ref that is
+ not an ancestor of the remote ref used to overwrite it.
+ This flag disables the check. What this means is that the
+ local repository can lose commits; use it with care.
diff --git a/Documentation/repository-layout.txt b/Documentation/repository-layout.txt
index 499b070..d20fa80 100644
--- a/Documentation/repository-layout.txt
+++ b/Documentation/repository-layout.txt
@@ -117,13 +117,6 @@ info/grafts::
listing their 40-byte hexadecimal object names separated
by a space and terminated by a newline.
-info/rev-cache::
- No higher-level tool currently takes advantage of this
- file, but it is generated when `git update-server-info`
- is run. It records the commit ancestry information of
- the commits in this repository in a concise binary
- format, and can be read with `git-show-rev-cache`.
-
info/exclude::
This file, by convention among Porcelains, stores the
exclude pattern list. `git status` looks at it, but
diff --git a/Makefile b/Makefile
index 9725b1a..877e0b8 100644
--- a/Makefile
+++ b/Makefile
@@ -92,7 +92,7 @@ SIMPLE_PROGRAMS = \
# ... and all the rest
PROGRAMS = \
- git-apply git-build-rev-cache git-cat-file \
+ git-apply git-cat-file \
git-checkout-index git-clone-pack git-commit-tree \
git-convert-objects git-diff-files \
git-diff-helper git-diff-index git-diff-stages \
@@ -103,12 +103,15 @@ PROGRAMS = \
git-peek-remote git-prune-packed git-read-tree \
git-receive-pack git-rev-list git-rev-parse \
git-rev-tree git-send-pack git-show-branch \
- git-show-index git-show-rev-cache git-ssh-fetch \
+ git-show-index git-ssh-fetch \
git-ssh-upload git-tar-tree git-unpack-file \
git-unpack-objects git-update-index git-update-server-info \
git-upload-pack git-verify-pack git-write-tree \
$(SIMPLE_PROGRAMS)
+# Backward compatibility -- to be removed in 0.99.8
+PROGRAMS += git-ssh-pull git-ssh-push
+
PYMODULES = \
gitMergeCommon.py
@@ -125,7 +128,7 @@ LIB_FILE=libgit.a
LIB_H = \
blob.h cache.h commit.h count-delta.h csum-file.h delta.h \
diff.h epoch.h object.h pack.h pkt-line.h quote.h refs.h \
- rev-cache.h run-command.h strbuf.h tag.h tree.h
+ run-command.h strbuf.h tag.h tree.h
DIFF_OBJS = \
diff.o diffcore-break.o diffcore-order.o diffcore-pathspec.o \
@@ -135,7 +138,7 @@ LIB_OBJS = \
blob.o commit.o connect.o count-delta.o csum-file.o \
date.o diff-delta.o entry.o ident.o index.o \
object.o pack-check.o patch-delta.o path.o pkt-line.o \
- quote.o read-cache.o refs.o rev-cache.o run-command.o \
+ quote.o read-cache.o refs.o run-command.o \
server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
tag.o tree.o usage.o $(DIFF_OBJS)
@@ -148,7 +151,8 @@ ifeq ($(shell uname -s),Darwin)
endif
ifeq ($(shell uname -s),SunOS)
NEEDS_SOCKET = YesPlease
- PLATFORM_DEFINES += -DNO_GETDOMAINNAME=1
+ NEEDS_NSL = YesPlease
+ PLATFORM_DEFINES += -D__EXTENSIONS__
endif
ifndef SHELL_PATH
@@ -195,6 +199,10 @@ ifdef NEEDS_SOCKET
LIBS += -lsocket
SIMPLE_LIB += -lsocket
endif
+ifdef NEEDS_NSL
+ LIBS += -lnsl
+ SIMPLE_LIB += -lnsl
+endif
DEFINES += '-DSHA1_HEADER=$(SHA1_HEADER)'
@@ -250,6 +258,8 @@ git-http-fetch: fetch.o
git-local-fetch: fetch.o
git-ssh-fetch: rsh.o fetch.o
git-ssh-upload: rsh.o
+git-ssh-pull: rsh.o fetch.o
+git-ssh-push: rsh.o
git-http-fetch: LIBS += -lcurl
git-rev-list: LIBS += $(OPENSSL_LIBSSL)
@@ -288,12 +298,12 @@ check:
### Installation rules
install: $(PROGRAMS) $(SCRIPTS)
- $(INSTALL) -m755 -d $(DESTDIR)$(bindir)
+ $(INSTALL) -d -m755 $(DESTDIR)$(bindir)
$(INSTALL) $(PROGRAMS) $(SCRIPTS) $(DESTDIR)$(bindir)
$(INSTALL) git-revert $(DESTDIR)$(bindir)/git-cherry-pick
sh ./cmd-rename.sh $(DESTDIR)$(bindir)
$(MAKE) -C templates install
- $(INSTALL) -m755 -d $(DESTDIR)$(GIT_PYTHON_DIR)
+ $(INSTALL) -d -m755 $(DESTDIR)$(GIT_PYTHON_DIR)
$(INSTALL) $(PYMODULES) $(DESTDIR)$(GIT_PYTHON_DIR)
install-doc:
diff --git a/build-rev-cache.c b/build-rev-cache.c
deleted file mode 100644
index 948898b..0000000
--- a/build-rev-cache.c
+++ /dev/null
@@ -1,56 +0,0 @@
-#include "refs.h"
-#include "cache.h"
-#include "commit.h"
-#include "rev-cache.h"
-
-static void process_head_list(int verbose)
-{
- char buf[512];
-
- while (fgets(buf, sizeof(buf), stdin)) {
- unsigned char sha1[20];
- struct commit *commit;
-
- if (get_sha1_hex(buf, sha1)) {
- error("ignoring: %s", buf);
- continue;
- }
- if (!(commit = lookup_commit_reference(sha1))) {
- error("not a commit: %s", sha1_to_hex(sha1));
- continue;
- }
- record_rev_cache(commit->object.sha1, verbose ? stderr : NULL);
- }
-}
-
-
-static const char *build_rev_cache_usage =
-"git-build-rev-cache <rev-cache-file> < list-of-heads";
-
-int main(int ac, char **av)
-{
- int verbose = 0;
- const char *path;
-
- while (1 < ac && av[1][0] == '-') {
- if (!strcmp(av[1], "-v"))
- verbose = 1;
- else
- usage(build_rev_cache_usage);
- ac--; av++;
- }
-
- if (ac != 2)
- usage(build_rev_cache_usage);
-
- path = av[1];
-
- /* read existing rev-cache */
- read_rev_cache(path, NULL, 0);
-
- process_head_list(verbose);
-
- /* update the rev-cache database by appending newly found one to it */
- write_rev_cache(path, path);
- return 0;
-}
diff --git a/cmd-rename.sh b/cmd-rename.sh
index 1edb037..ada33fb 100755
--- a/cmd-rename.sh
+++ b/cmd-rename.sh
@@ -42,12 +42,14 @@ git-tag-script git-tag
git-verify-tag-script git-verify-tag
git-http-pull git-http-fetch
git-local-pull git-local-fetch
-git-ssh-pull git-ssh-fetch
git-checkout-cache git-checkout-index
git-diff-cache git-diff-index
git-merge-cache git-merge-index
git-update-cache git-update-index
-git-ssh-push git-ssh-upload
git-convert-cache git-convert-objects
git-fsck-cache git-fsck-objects
EOF
+
+# These two are a bit more than symlinks now.
+# git-ssh-push git-ssh-upload
+# git-ssh-pull git-ssh-fetch
diff --git a/commit.c b/commit.c
index 2f73cf3..f735f98 100644
--- a/commit.c
+++ b/commit.c
@@ -3,6 +3,8 @@
#include "commit.h"
#include "cache.h"
+int save_commit_buffer = 1;
+
struct sort_node
{
/*
@@ -264,7 +266,7 @@ int parse_commit(struct commit *item)
sha1_to_hex(item->object.sha1));
}
ret = parse_commit_buffer(item, buffer, size);
- if (!ret) {
+ if (save_commit_buffer && !ret) {
item->buffer = buffer;
return 0;
}
diff --git a/commit.h b/commit.h
index 9dda2f0..30702ca 100644
--- a/commit.h
+++ b/commit.h
@@ -17,6 +17,7 @@ struct commit {
char *buffer;
};
+extern int save_commit_buffer;
extern const char *commit_type;
struct commit *lookup_commit(const unsigned char *sha1);
diff --git a/convert-objects.c b/convert-objects.c
index 073cab5..9ad0c77 100644
--- a/convert-objects.c
+++ b/convert-objects.c
@@ -1,5 +1,4 @@
#define _XOPEN_SOURCE /* glibc2 needs this */
-#define __EXTENSIONS__ /* solaris needs this */
#include <time.h>
#include <ctype.h>
#include "cache.h"
diff --git a/debian/control b/debian/control
index 33a8f85..5d75c32 100644
--- a/debian/control
+++ b/debian/control
@@ -2,13 +2,13 @@ Source: git-core
Section: devel
Priority: optional
Maintainer: Junio C Hamano <junkio@cox.net>
-Build-Depends-Indep: libz-dev, libssl-dev, libcurl3-dev, asciidoc (>= 6.0.3), xmlto, debhelper (>= 4.0.0)
+Build-Depends-Indep: libz-dev, libssl-dev, libcurl3-dev, asciidoc (>= 6.0.3), xmlto, debhelper (>= 4.0.0), bc
Standards-Version: 3.6.1
Package: git-core
Architecture: any
Depends: ${shlibs:Depends}, ${perl:Depends}, ${misc:Depends}, patch, rcs
-Recommends: rsync, curl, ssh, libmail-sendmail-perl, libemail-valid-perl, python (>= 2.4.0)
+Recommends: rsync, curl, ssh, libmail-sendmail-perl, libemail-valid-perl, python (>= 2.4.0), less
Suggests: cogito
Conflicts: git, cogito (<< 0.13)
Description: The git content addressable filesystem
diff --git a/debian/rules b/debian/rules
index 1a53ca2..568d430 100755
--- a/debian/rules
+++ b/debian/rules
@@ -41,7 +41,7 @@ MAN_DESTDIR := $(DESTDIR)/$(MANDIR)
build: debian/build-stamp
debian/build-stamp:
dh_testdir
- $(MAKE) prefix=$(PREFIX) PYTHON_PATH=/usr/bin/python2.4 all doc
+ $(MAKE) prefix=$(PREFIX) PYTHON_PATH=/usr/bin/python2.4 all doc test
touch debian/build-stamp
debian-clean:
diff --git a/diff-tree.c b/diff-tree.c
index fc87902..e8f5d1b 100644
--- a/diff-tree.c
+++ b/diff-tree.c
@@ -370,6 +370,7 @@ static int diff_tree_commit(const unsigned char *commit, const char *name)
}
offset += 48;
}
+ free(buf);
return 0;
}
diff --git a/diff.c b/diff.c
index f8e3cbf..d8d20c2 100644
--- a/diff.c
+++ b/diff.c
@@ -214,14 +214,10 @@ struct diff_filespec *alloc_filespec(const char *path)
{
int namelen = strlen(path);
struct diff_filespec *spec = xmalloc(sizeof(*spec) + namelen + 1);
+
+ memset(spec, 0, sizeof(*spec));
spec->path = (char *)(spec + 1);
- strcpy(spec->path, path);
- spec->should_free = spec->should_munmap = 0;
- spec->xfrm_flags = 0;
- spec->size = 0;
- spec->data = NULL;
- spec->mode = 0;
- memset(spec->sha1, 0, 20);
+ memcpy(spec->path, path, namelen+1);
return spec;
}
@@ -406,13 +402,14 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
return 0;
}
-void diff_free_filespec(struct diff_filespec *s)
+void diff_free_filespec_data(struct diff_filespec *s)
{
if (s->should_free)
free(s->data);
else if (s->should_munmap)
munmap(s->data, s->size);
- free(s);
+ s->should_free = s->should_munmap = 0;
+ s->data = NULL;
}
static void prep_temp_blob(struct diff_tempfile *temp,
@@ -765,14 +762,17 @@ struct diff_filepair *diff_queue(struct diff_queue_struct *queue,
dp->status = 0;
dp->source_stays = 0;
dp->broken_pair = 0;
- diff_q(queue, dp);
+ if (queue)
+ diff_q(queue, dp);
return dp;
}
void diff_free_filepair(struct diff_filepair *p)
{
- diff_free_filespec(p->one);
- diff_free_filespec(p->two);
+ diff_free_filespec_data(p->one);
+ diff_free_filespec_data(p->two);
+ free(p->one);
+ free(p->two);
free(p);
}
diff --git a/diffcore-break.c b/diffcore-break.c
index b0c8461..06f9a7f 100644
--- a/diffcore-break.c
+++ b/diffcore-break.c
@@ -231,8 +231,8 @@ static void merge_broken(struct diff_filepair *p,
dp = diff_queue(outq, d->one, c->two);
dp->score = p->score;
- diff_free_filespec(d->two);
- diff_free_filespec(c->one);
+ diff_free_filespec_data(d->two);
+ diff_free_filespec_data(c->one);
free(d);
free(c);
}
diff --git a/diffcore-rename.c b/diffcore-rename.c
index dbc8522..092cf68 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -47,7 +47,8 @@ static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two,
if (first < rename_dst_nr)
memmove(rename_dst + first + 1, rename_dst + first,
(rename_dst_nr - first - 1) * sizeof(*rename_dst));
- rename_dst[first].two = two;
+ rename_dst[first].two = alloc_filespec(two->path);
+ fill_filespec(rename_dst[first].two, two->sha1, two->mode);
rename_dst[first].pair = NULL;
return &(rename_dst[first]);
}
@@ -201,8 +202,7 @@ static int estimate_similarity(struct diff_filespec *src,
return score;
}
-static void record_rename_pair(struct diff_queue_struct *renq,
- int dst_index, int src_index, int score)
+static void record_rename_pair(int dst_index, int src_index, int score)
{
struct diff_filespec *one, *two, *src, *dst;
struct diff_filepair *dp;
@@ -218,7 +218,7 @@ static void record_rename_pair(struct diff_queue_struct *renq,
two = alloc_filespec(dst->path);
fill_filespec(two, dst->sha1, dst->mode);
- dp = diff_queue(renq, one, two);
+ dp = diff_queue(NULL, one, two);
dp->score = score;
dp->source_stays = rename_src[src_index].src_path_left;
rename_dst[dst_index].pair = dp;
@@ -252,15 +252,14 @@ static int compute_stays(struct diff_queue_struct *q,
void diffcore_rename(int detect_rename, int minimum_score)
{
struct diff_queue_struct *q = &diff_queued_diff;
- struct diff_queue_struct renq, outq;
+ struct diff_queue_struct outq;
struct diff_score *mx;
- int i, j;
+ int i, j, rename_count;
int num_create, num_src, dst_cnt;
if (!minimum_score)
minimum_score = DEFAULT_RENAME_SCORE;
- renq.queue = NULL;
- renq.nr = renq.alloc = 0;
+ rename_count = 0;
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
@@ -292,19 +291,19 @@ void diffcore_rename(int detect_rename, int minimum_score)
struct diff_filespec *one = rename_src[j].one;
if (!is_exact_match(one, two))
continue;
- record_rename_pair(&renq, i, j, MAX_SCORE);
+ record_rename_pair(i, j, MAX_SCORE);
+ rename_count++;
break; /* we are done with this entry */
}
}
- diff_debug_queue("done detecting exact", &renq);
/* Have we run out the created file pool? If so we can avoid
* doing the delta matrix altogether.
*/
- if (renq.nr == rename_dst_nr)
+ if (rename_count == rename_dst_nr)
goto cleanup;
- num_create = (rename_dst_nr - renq.nr);
+ num_create = (rename_dst_nr - rename_count);
num_src = rename_src_nr;
mx = xmalloc(sizeof(*mx) * num_create * num_src);
for (dst_cnt = i = 0; i < rename_dst_nr; i++) {
@@ -330,14 +329,14 @@ void diffcore_rename(int detect_rename, int minimum_score)
continue; /* already done, either exact or fuzzy. */
if (mx[i].score < minimum_score)
break; /* there is no more usable pair. */
- record_rename_pair(&renq, mx[i].dst, mx[i].src, mx[i].score);
+ record_rename_pair(mx[i].dst, mx[i].src, mx[i].score);
+ rename_count++;
}
free(mx);
- diff_debug_queue("done detecting fuzzy", &renq);
cleanup:
/* At this point, we have found some renames and copies and they
- * are kept in renq. The original list is still in *q.
+ * are recorded in rename_dst. The original list is still in *q.
*/
outq.queue = NULL;
outq.nr = outq.alloc = 0;
@@ -372,9 +371,9 @@ void diffcore_rename(int detect_rename, int minimum_score)
*
* (1) this is a broken delete and the counterpart
* broken create remains in the output; or
- * (2) this is not a broken delete, and renq does
- * not have a rename/copy to move p->one->path
- * out.
+ * (2) this is not a broken delete, and rename_dst
+ * does not have a rename/copy to move p->one->path
+ * out of existence.
*
* Otherwise, the counterpart broken create
* has been turned into a rename-edit; or
@@ -390,11 +389,16 @@ void diffcore_rename(int detect_rename, int minimum_score)
pair_to_free = p;
}
else {
- for (j = 0; j < renq.nr; j++)
- if (!strcmp(renq.queue[j]->one->path,
- p->one->path))
- break;
- if (j < renq.nr)
+ for (j = 0; j < rename_dst_nr; j++) {
+ if (!rename_dst[j].pair)
+ continue;
+ if (strcmp(rename_dst[j].pair->
+ one->path,
+ p->one->path))
+ continue;
+ break;
+ }
+ if (j < rename_dst_nr)
/* this path remains */
pair_to_free = p;
}
@@ -416,7 +420,6 @@ void diffcore_rename(int detect_rename, int minimum_score)
}
diff_debug_queue("done copying original", &outq);
- free(renq.queue);
free(q->queue);
*q = outq;
diff_debug_queue("done collapsing", q);
@@ -438,6 +441,11 @@ void diffcore_rename(int detect_rename, int minimum_score)
}
}
+ for (i = 0; i < rename_dst_nr; i++) {
+ diff_free_filespec_data(rename_dst[i].two);
+ free(rename_dst[i].two);
+ }
+
free(rename_dst);
rename_dst = NULL;
rename_dst_nr = rename_dst_alloc = 0;
diff --git a/diffcore.h b/diffcore.h
index 633d1ae..f1b5ca7 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -43,7 +43,7 @@ extern void fill_filespec(struct diff_filespec *, const unsigned char *,
unsigned short);
extern int diff_populate_filespec(struct diff_filespec *, int);
-extern void diff_free_filespec(struct diff_filespec *);
+extern void diff_free_filespec_data(struct diff_filespec *);
struct diff_filepair {
struct diff_filespec *one;
diff --git a/fetch.c b/fetch.c
index e874538..1d95ce0 100644
--- a/fetch.c
+++ b/fetch.c
@@ -33,42 +33,51 @@ static void report_missing(const char *what, const unsigned char *missing)
what, missing_hex, sha1_to_hex(current_commit_sha1));
}
-static int make_sure_we_have_it(const char *what, unsigned char *sha1)
-{
- int status = 0;
-
- if (!has_sha1_file(sha1)) {
- status = fetch(sha1);
- if (status && what)
- report_missing(what, sha1);
- }
- return status;
-}
-
static int process(unsigned char *sha1, const char *type);
static int process_tree(struct tree *tree)
{
- struct tree_entry_list *entries;
+ struct tree_entry_list *entry;
if (parse_tree(tree))
return -1;
- for (entries = tree->entries; entries; entries = entries->next) {
- if (process(entries->item.any->sha1,
- entries->directory ? tree_type : blob_type))
+ entry = tree->entries;
+ tree->entries = NULL;
+ while (entry) {
+ struct tree_entry_list *next = entry->next;
+ if (process(entry->item.any->sha1,
+ entry->directory ? tree_type : blob_type))
return -1;
+ free(entry);
+ entry = next;
}
return 0;
}
+#define COMPLETE 1U
+#define TO_FETCH 2U
+#define TO_SCAN 4U
+#define SCANNED 8U
+
+static struct commit_list *complete = NULL;
+
static int process_commit(struct commit *commit)
{
if (parse_commit(commit))
return -1;
+ while (complete && complete->item->date >= commit->date) {
+ pop_most_recent_commit(&complete, COMPLETE);
+ }
+
+ if (commit->object.flags & COMPLETE)
+ return 0;
+
memcpy(current_commit_sha1, commit->object.sha1, 20);
+ pull_say("walk %s\n", sha1_to_hex(commit->object.sha1));
+
if (get_tree) {
if (process(commit->tree->object.sha1, tree_type))
return -1;
@@ -78,10 +87,7 @@ static int process_commit(struct commit *commit)
if (get_history) {
struct commit_list *parents = commit->parents;
for (; parents; parents = parents->next) {
- if (has_sha1_file(parents->item->object.sha1))
- continue;
- if (process(parents->item->object.sha1,
- commit_type))
+ if (process(parents->item->object.sha1, commit_type))
return -1;
}
}
@@ -100,6 +106,10 @@ static struct object_list **process_queue_end = &process_queue;
static int process_object(struct object *obj)
{
+ if (obj->flags & SCANNED)
+ return 0;
+ obj->flags |= SCANNED;
+
if (obj->type == commit_type) {
if (process_commit((struct commit *)obj))
return -1;
@@ -126,17 +136,23 @@ static int process_object(struct object *obj)
static int process(unsigned char *sha1, const char *type)
{
struct object *obj = lookup_object_type(sha1, type);
+
if (has_sha1_file(sha1)) {
parse_object(sha1);
/* We already have it, so we should scan it now. */
- return process_object(obj);
+ if (obj->flags & (SCANNED | TO_SCAN))
+ return 0;
+ object_list_insert(obj, process_queue_end);
+ process_queue_end = &(*process_queue_end)->next;
+ obj->flags |= TO_SCAN;
+ return 0;
}
- if (object_list_contains(process_queue, obj))
+ if (obj->flags & (COMPLETE | TO_FETCH))
return 0;
object_list_insert(obj, process_queue_end);
process_queue_end = &(*process_queue_end)->next;
+ obj->flags |= TO_FETCH;
- //fprintf(stderr, "prefetch %s\n", sha1_to_hex(sha1));
prefetch(sha1);
return 0;
@@ -144,21 +160,27 @@ static int process(unsigned char *sha1, const char *type)
static int loop(void)
{
+ struct object_list *elem;
+
while (process_queue) {
struct object *obj = process_queue->item;
- /*
- fprintf(stderr, "%d objects to pull\n",
- object_list_length(process_queue));
- */
- process_queue = process_queue->next;
+ elem = process_queue;
+ process_queue = elem->next;
+ free(elem);
if (!process_queue)
process_queue_end = &process_queue;
- //fprintf(stderr, "fetch %s\n", sha1_to_hex(obj->sha1));
-
- if (make_sure_we_have_it(obj->type ? obj->type : "object",
- obj->sha1))
- return -1;
+ /* If we are not scanning this object, we placed it in
+ * the queue because we needed to fetch it first.
+ */
+ if (! (obj->flags & TO_SCAN)) {
+ if (fetch(obj->sha1)) {
+ report_missing(obj->type
+ ? obj->type
+ : "object", obj->sha1);
+ return -1;
+ }
+ }
if (!obj->type)
parse_object(obj->sha1);
if (process_object(obj))
@@ -179,18 +201,30 @@ static int interpret_target(char *target, unsigned char *sha1)
return -1;
}
+static int mark_complete(const char *path, const unsigned char *sha1)
+{
+ struct commit *commit = lookup_commit_reference_gently(sha1, 1);
+ if (commit) {
+ commit->object.flags |= COMPLETE;
+ insert_by_date(commit, &complete);
+ }
+ return 0;
+}
int pull(char *target)
{
unsigned char sha1[20];
int fd = -1;
+ save_commit_buffer = 0;
if (write_ref && current_ref) {
fd = lock_ref_sha1(write_ref, current_ref);
if (fd < 0)
return -1;
}
+ for_each_ref(mark_complete);
+
if (interpret_target(target, sha1))
return error("Could not interpret %s as something to pull",
target);
diff --git a/git-bisect.sh b/git-bisect.sh
index a5be3a7..8dc77c9 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -110,7 +110,7 @@ bisect_next_check() {
}
bisect_auto_next() {
- bisect_next_check && bisect_next
+ bisect_next_check && bisect_next || :
}
bisect_next() {
diff --git a/git-branch.sh b/git-branch.sh
index 81b9e6c..dcec2a9 100755
--- a/git-branch.sh
+++ b/git-branch.sh
@@ -3,7 +3,7 @@
. git-sh-setup || die "Not a git archive"
usage () {
- echo >&2 "usage: $(basename $0)"' [<branchname> [start-point]]
+ echo >&2 "usage: $(basename $0)"' [-d <branch>] | [<branch> [start-point]]
If no arguments, show available branches and mark current branch with a star.
If one argument, create a new branch <branchname> based off of current HEAD.
@@ -12,6 +12,59 @@ If two arguments, create a new branch <branchname> based off of <start-point>.
exit 1
}
+delete_branch () {
+ option="$1" branch_name="$2"
+ headref=$(readlink "$GIT_DIR/HEAD" | sed -e 's|^refs/heads/||')
+ case ",$headref," in
+ ",$branch_name,")
+ die "Cannot delete the branch you are on." ;;
+ ,,)
+ die "What branch are you on anyway?" ;;
+ esac
+ branch=$(cat "$GIT_DIR/refs/heads/$branch_name") &&
+ branch=$(git-rev-parse --verify "$branch^0") ||
+ die "Seriously, what branch are you talking about?"
+ case "$option" in
+ -D)
+ ;;
+ *)
+ mbs=$(git-merge-base -a "$branch" HEAD | tr '\012' ' ')
+ case " $mbs " in
+ *' '$branch' '*)
+ # the merge base of branch and HEAD contains branch --
+ # which means that the HEAD contains everything in the HEAD.
+ ;;
+ *)
+ echo >&2 "The branch '$branch_name' is not a strict subset of your current HEAD.
+If you are sure you want to delete it, run 'git branch -D $branch_name'."
+ exit 1
+ ;;
+ esac
+ ;;
+ esac
+ rm -f "$GIT_DIR/refs/heads/$branch_name"
+ echo "Deleted branch $branch_name."
+ exit 0
+}
+
+while case "$#,$1" in 0,*) break ;; *,-*) ;; *) break ;; esac
+do
+ case "$1" in
+ -d | -D)
+ delete_branch "$1" "$2"
+ exit
+ ;;
+ --)
+ shift
+ break
+ ;;
+ -*)
+ usage
+ ;;
+ esac
+ shift
+done
+
case "$#" in
0)
headref=$(readlink "$GIT_DIR/HEAD" | sed -e 's|^refs/heads/||')
@@ -36,11 +89,6 @@ case "$#" in
esac
branchname="$1"
-case "$branchname" in
--*)
- usage;;
-esac
-
rev=$(git-rev-parse --verify "$head") || exit
[ -e "$GIT_DIR/refs/heads/$branchname" ] && die "$branchname already exists"
diff --git a/git-checkout.sh b/git-checkout.sh
index 4a605cd..e02c7af 100755
--- a/git-checkout.sh
+++ b/git-checkout.sh
@@ -22,7 +22,8 @@ while [ "$#" != "0" ]; do
force=1
;;
*)
- rev=$(git-rev-parse --verify "$arg^0") || exit
+ rev=$(git-rev-parse --verify "$arg^0" 2>/dev/null) ||
+ die "hey dummy, branch '$arg' doesn't exist."
if [ -z "$rev" ]; then
echo "unknown flag $arg"
exit 1
diff --git a/git-clone.sh b/git-clone.sh
index a21f13a..bfb8fd6 100755
--- a/git-clone.sh
+++ b/git-clone.sh
@@ -144,8 +144,32 @@ yes,yes)
*)
case "$repo" in
rsync://*)
- rsync $quiet -avz --ignore-existing "$repo/objects/" "$D/.git/objects/" &&
- rsync $quiet -avz --ignore-existing "$repo/refs/" "$D/.git/refs/"
+ rsync $quiet -av --ignore-existing \
+ --exclude info "$repo/objects/" "$D/.git/objects/" &&
+ rsync $quiet -av --ignore-existing \
+ --exclude info "$repo/refs/" "$D/.git/refs/" || exit
+
+ # Look at objects/info/alternates for rsync -- http will
+ # support it natively and git native ones will do it on the
+ # remote end. Not having that file is not a crime.
+ rsync -q "$repo/objects/info/alternates" "$D/.git/TMP_ALT" ||
+ rm -f "$D/.git/TMP_ALT"
+ if test -f "$D/.git/TMP_ALT"
+ then
+ ( cd $D &&
+ . git-parse-remote &&
+ resolve_alternates "$repo" <"./.git/TMP_ALT" ) |
+ while read alt
+ do
+ case "$alt" in 'bad alternate: '*) die "$alt";; esac
+ case "$quiet" in
+ '') echo >&2 "Getting alternate: $alt" ;;
+ esac
+ rsync $quiet -av --ignore-existing \
+ --exclude info "$alt" "$D/.git/objects" || exit
+ done
+ rm -f "$D/.git/TMP_ALT"
+ fi
;;
http://*)
clone_dumb_http "$repo" "$D"
diff --git a/git-core.spec.in b/git-core.spec.in
index f98f8db..6c17d52 100644
--- a/git-core.spec.in
+++ b/git-core.spec.in
@@ -1,16 +1,15 @@
# Pass --without docs to rpmbuild if you don't want the documetnation
Name: git-core
Version: @@VERSION@@
-Release: 1
-Vendor: Junio C Hamano <junkio@cox.net>
+Release: 1%{?dist}
Summary: Git core and tools
License: GPL
Group: Development/Tools
URL: http://kernel.org/pub/software/scm/git/
Source: http://kernel.org/pub/software/scm/git/%{name}-%{version}.tar.gz
BuildRequires: zlib-devel, openssl-devel, curl-devel %{!?_without_docs:, xmlto, asciidoc > 6.0.3}
-BuildRoot: %{_tmppath}/%{name}-%{version}-root
-Requires: sh-utils, curl, diffutils, rsync, rcs, openssh-clients, perl, python >= 2.4, tk
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+Requires: rsync, rcs, curl, less, openssh-clients, python >= 2.4, tk
%description
This is a stupid (but extremely fast) directory content manager. It
@@ -24,7 +23,7 @@ elsewhere for tools for ordinary humans layered on top of this.
%setup -q
%build
-make prefix=%{_prefix} all %{!?_without_docs: doc}
+make COPTS="$RPM_OPT_FLAGS" prefix=%{_prefix} all %{!?_without_docs: doc}
%install
rm -rf $RPM_BUILD_ROOT
@@ -37,17 +36,35 @@ rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%{_bindir}/*
-%{_datadir}/git-core/templates/*
+%{_datadir}/git-core/
%doc README COPYING Documentation/*.txt
%{!?_without_docs: %doc Documentation/*.html }
%{!?_without_docs: %{_mandir}/man1/*.1*}
%{!?_without_docs: %{_mandir}/man7/*.7*}
%changelog
+* Fri Sep 16 2005 Chris Wright <chrisw@osdl.org> 0.99.6-1
+- update to 0.99.6
+
+* Fri Sep 16 2005 Horst H. von Brand <vonbrand@inf.utfsm.cl>
+- Linus noticed that less is required, added to the dependencies
+
* Sun Sep 11 2005 Horst H. von Brand <vonbrand@inf.utfsm.cl>
- Updated dependencies
- Don't assume manpages are gzipped
+* Thu Aug 18 2005 Chris Wright <chrisw@osdl.org> 0.99.4-4
+- drop sh_utils, sh-utils, diffutils, mktemp, and openssl Requires
+- use RPM_OPT_FLAGS in spec file, drop patch0
+
+* Wed Aug 17 2005 Tom "spot" Callaway <tcallawa@redhat.com> 0.99.4-3
+- use dist tag to differentiate between branches
+- use rpm optflags by default (patch0)
+- own %{_datadir}/git-core/
+
+* Mon Aug 15 2005 Chris Wright <chrisw@osdl.org>
+- update spec file to fix Buildroot, Requires, and drop Vendor
+
* Sun Aug 07 2005 Horst H. von Brand <vonbrand@inf.utfsm.cl>
- Redid the description
- Cut overlong make line, loosened changelog a bit
diff --git a/git-fetch.sh b/git-fetch.sh
index 2273944..72f17ab 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -183,12 +183,30 @@ do
;;
rsync://*)
TMP_HEAD="$GIT_DIR/TMP_HEAD"
- rsync -L "$remote/$remote_name" "$TMP_HEAD" || exit 1
+ rsync -L -q "$remote/$remote_name" "$TMP_HEAD" || exit 1
head=$(git-rev-parse TMP_HEAD)
rm -f "$TMP_HEAD"
test "$rsync_slurped_objects" || {
- rsync -avz --ignore-existing "$remote/objects/" \
- "$GIT_OBJECT_DIRECTORY/" || exit
+ rsync -av --ignore-existing --exclude info \
+ "$remote/objects/" "$GIT_OBJECT_DIRECTORY/" || exit
+
+ # Look at objects/info/alternates for rsync -- http will
+ # support it natively and git native ones will do it on the remote
+ # end. Not having that file is not a crime.
+ rsync -q "$remote/objects/info/alternates" "$GIT_DIR/TMP_ALT" ||
+ rm -f "$GIT_DIR/TMP_ALT"
+ if test -f "$GIT_DIR/TMP_ALT"
+ then
+ resolve_alternates "$remote" <"$GIT_DIR/TMP_ALT" |
+ while read alt
+ do
+ case "$alt" in 'bad alternate: '*) die "$alt";; esac
+ echo >&2 "Getting alternate: $alt"
+ rsync -av --ignore-existing --exclude info \
+ "$alt" "$GIT_OBJECT_DIRECTORY/" || exit
+ done
+ rm -f "$GIT_DIR/TMP_ALT"
+ fi
rsync_slurped_objects=t
}
;;
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index 3c5d94b..a9db0cd 100755
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -153,3 +153,24 @@ get_remote_refs_for_fetch () {
;;
esac
}
+
+resolve_alternates () {
+ # original URL (xxx.git)
+ top_=`expr "$1" : '\([^:]*:/*[^/]*\)/'`
+ while read path
+ do
+ case "$path" in
+ \#* | '')
+ continue ;;
+ /*)
+ echo "$top_$path/" ;;
+ ../*)
+ # relative -- ugly but seems to work.
+ echo "$1/objects/$path/" ;;
+ *)
+ # exit code may not be caught by the reader.
+ echo "bad alternate: $path"
+ exit 1 ;;
+ esac
+ done
+}
diff --git a/git-pull.sh b/git-pull.sh
index c1b4474..8cf39e7 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -25,8 +25,10 @@ then
fi
merge_head=$(sed -e 's/ .*//' "$GIT_DIR"/FETCH_HEAD | tr '\012' ' ')
-merge_name=$(sed -e 's/^[0-9a-f]* //' "$GIT_DIR"/FETCH_HEAD |
- tr '\012' ' ')
+merge_name=$(
+ perl -e 'print join("; ", map { chomp; s/^[0-9a-f]* //; $_ } <>)' \
+ "$GIT_DIR"/FETCH_HEAD
+)
case "$merge_head" in
'')
diff --git a/git-repack.sh b/git-repack.sh
index 064c85c..b395d0e 100755
--- a/git-repack.sh
+++ b/git-repack.sh
@@ -58,7 +58,15 @@ then
# all-into-one is used.
if test "$all_into_one" != '' && test "$existing" != ''
then
- ( cd "$PACKDIR" && rm -f $existing )
+ ( cd "$PACKDIR" &&
+ for e in $existing
+ do
+ case "$e" in
+ ./pack-$name.pack | ./pack-$name.idx) ;;
+ *) rm -f $e ;;
+ esac
+ done
+ )
fi
fi
diff --git a/git-shortlog.perl b/git-shortlog.perl
index 107c895..8f0984b 100755
--- a/git-shortlog.perl
+++ b/git-shortlog.perl
@@ -108,7 +108,7 @@ sub changelog_input {
if ($pstate == 1) {
my ($email);
- next unless /^Author: (.*)<(.*)>.*$/;
+ next unless /^[Aa]uthor:? (.*)<(.*)>.*$/;
$n_records++;
diff --git a/http-fetch.c b/http-fetch.c
index 4e564fc..17051fe 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -14,8 +14,19 @@
#endif
static CURL *curl;
+static struct curl_slist *no_pragma_header;
-static char *base;
+static char *initial_base;
+
+struct alt_base
+{
+ char *base;
+ int got_indices;
+ struct packed_git *packs;
+ struct alt_base *next;
+};
+
+struct alt_base *alt = NULL;
static SHA_CTX c;
static z_stream stream;
@@ -71,11 +82,9 @@ void prefetch(unsigned char *sha1)
{
}
-static int got_indices = 0;
-
-static struct packed_git *packs = NULL;
+static int got_alternates = 0;
-static int fetch_index(unsigned char *sha1)
+static int fetch_index(struct alt_base *repo, unsigned char *sha1)
{
char *filename;
char *url;
@@ -89,9 +98,9 @@ static int fetch_index(unsigned char *sha1)
fprintf(stderr, "Getting index for pack %s\n",
sha1_to_hex(sha1));
- url = xmalloc(strlen(base) + 64);
+ url = xmalloc(strlen(repo->base) + 64);
sprintf(url, "%s/objects/pack/pack-%s.idx",
- base, sha1_to_hex(sha1));
+ repo->base, sha1_to_hex(sha1));
filename = sha1_pack_index_name(sha1);
indexfile = fopen(filename, "w");
@@ -102,6 +111,7 @@ static int fetch_index(unsigned char *sha1)
curl_easy_setopt(curl, CURLOPT_FILE, indexfile);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_pragma_header);
if (curl_easy_perform(curl)) {
fclose(indexfile);
@@ -112,22 +122,92 @@ static int fetch_index(unsigned char *sha1)
return 0;
}
-static int setup_index(unsigned char *sha1)
+static int setup_index(struct alt_base *repo, unsigned char *sha1)
{
struct packed_git *new_pack;
if (has_pack_file(sha1))
return 0; // don't list this as something we can get
- if (fetch_index(sha1))
+ if (fetch_index(repo, sha1))
return -1;
new_pack = parse_pack_index(sha1);
- new_pack->next = packs;
- packs = new_pack;
+ new_pack->next = repo->packs;
+ repo->packs = new_pack;
return 0;
}
-static int fetch_indices(void)
+static int fetch_alternates(char *base)
+{
+ int ret = 0;
+ struct buffer buffer;
+ char *url;
+ char *data;
+ int i = 0;
+ if (got_alternates)
+ return 0;
+ data = xmalloc(4096);
+ buffer.size = 4096;
+ buffer.posn = 0;
+ buffer.buffer = data;
+
+ if (get_verbosely)
+ fprintf(stderr, "Getting alternates list\n");
+
+ url = xmalloc(strlen(base) + 31);
+ sprintf(url, "%s/objects/info/http-alternates", base);
+
+ curl_easy_setopt(curl, CURLOPT_FILE, &buffer);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+
+ if (curl_easy_perform(curl) || !buffer.posn) {
+ sprintf(url, "%s/objects/info/alternates", base);
+
+ curl_easy_setopt(curl, CURLOPT_FILE, &buffer);
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
+ curl_easy_setopt(curl, CURLOPT_URL, url);
+
+ if (curl_easy_perform(curl)) {
+ return 0;
+ }
+ }
+
+ while (i < buffer.posn) {
+ int posn = i;
+ while (posn < buffer.posn && data[posn] != '\n')
+ posn++;
+ if (data[posn] == '\n') {
+ if (data[i] == '/') {
+ int serverlen = strchr(base + 8, '/') - base;
+ // skip 'objects' at end
+ char *target =
+ xmalloc(serverlen + posn - i - 6);
+ struct alt_base *newalt;
+ strncpy(target, base, serverlen);
+ strncpy(target + serverlen, data + i,
+ posn - i - 7);
+ target[serverlen + posn - i - 7] = '\0';
+ if (get_verbosely)
+ fprintf(stderr,
+ "Also look at %s\n", target);
+ newalt = xmalloc(sizeof(*newalt));
+ newalt->next = alt;
+ newalt->base = target;
+ newalt->got_indices = 0;
+ newalt->packs = NULL;
+ alt = newalt;
+ ret++;
+ }
+ }
+ i = posn + 1;
+ }
+ got_alternates = 1;
+
+ return ret;
+}
+
+static int fetch_indices(struct alt_base *repo)
{
unsigned char sha1[20];
char *url;
@@ -135,7 +215,7 @@ static int fetch_indices(void)
char *data;
int i = 0;
- if (got_indices)
+ if (repo->got_indices)
return 0;
data = xmalloc(4096);
@@ -146,18 +226,19 @@ static int fetch_indices(void)
if (get_verbosely)
fprintf(stderr, "Getting pack list\n");
- url = xmalloc(strlen(base) + 21);
- sprintf(url, "%s/objects/info/packs", base);
+ url = xmalloc(strlen(repo->base) + 21);
+ sprintf(url, "%s/objects/info/packs", repo->base);
curl_easy_setopt(curl, CURLOPT_FILE, &buffer);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL);
if (curl_easy_perform(curl)) {
return error("Unable to get pack index %s", url);
}
- do {
+ while (i < buffer.posn) {
switch (data[i]) {
case 'P':
i++;
@@ -165,7 +246,7 @@ static int fetch_indices(void)
!strncmp(data + i, " pack-", 6) &&
!strncmp(data + i + 46, ".pack\n", 6)) {
get_sha1_hex(data + i + 6, sha1);
- setup_index(sha1);
+ setup_index(repo, sha1);
i += 51;
break;
}
@@ -174,13 +255,13 @@ static int fetch_indices(void)
i++;
}
i++;
- } while (i < buffer.posn);
+ }
- got_indices = 1;
+ repo->got_indices = 1;
return 0;
}
-static int fetch_pack(unsigned char *sha1)
+static int fetch_pack(struct alt_base *repo, unsigned char *sha1)
{
char *url;
struct packed_git *target;
@@ -188,12 +269,11 @@ static int fetch_pack(unsigned char *sha1)
FILE *packfile;
char *filename;
- if (fetch_indices())
+ if (fetch_indices(repo))
return -1;
- target = find_sha1_pack(sha1, packs);
+ target = find_sha1_pack(sha1, repo->packs);
if (!target)
- return error("Couldn't get %s: not separate or in any pack",
- sha1_to_hex(sha1));
+ return -1;
if (get_verbosely) {
fprintf(stderr, "Getting pack %s\n",
@@ -202,9 +282,9 @@ static int fetch_pack(unsigned char *sha1)
sha1_to_hex(sha1));
}
- url = xmalloc(strlen(base) + 65);
+ url = xmalloc(strlen(repo->base) + 65);
sprintf(url, "%s/objects/pack/pack-%s.pack",
- base, sha1_to_hex(target->sha1));
+ repo->base, sha1_to_hex(target->sha1));
filename = sha1_pack_name(target->sha1);
packfile = fopen(filename, "w");
@@ -215,6 +295,7 @@ static int fetch_pack(unsigned char *sha1)
curl_easy_setopt(curl, CURLOPT_FILE, packfile);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite);
curl_easy_setopt(curl, CURLOPT_URL, url);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_pragma_header);
if (curl_easy_perform(curl)) {
fclose(packfile);
@@ -223,7 +304,7 @@ static int fetch_pack(unsigned char *sha1)
fclose(packfile);
- lst = &packs;
+ lst = &repo->packs;
while (*lst != target)
lst = &((*lst)->next);
*lst = (*lst)->next;
@@ -233,7 +314,7 @@ static int fetch_pack(unsigned char *sha1)
return 0;
}
-int fetch(unsigned char *sha1)
+int fetch_object(struct alt_base *repo, unsigned char *sha1)
{
char *hex = sha1_to_hex(sha1);
char *filename = sha1_file_name(sha1);
@@ -255,10 +336,11 @@ int fetch(unsigned char *sha1)
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(curl, CURLOPT_FILE, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_sha1_file);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_pragma_header);
- url = xmalloc(strlen(base) + 50);
- strcpy(url, base);
- posn = url + strlen(base);
+ url = xmalloc(strlen(repo->base) + 50);
+ strcpy(url, repo->base);
+ posn = url + strlen(repo->base);
strcpy(posn, "objects/");
posn += 8;
memcpy(posn, hex, 2);
@@ -270,9 +352,7 @@ int fetch(unsigned char *sha1)
if (curl_easy_perform(curl)) {
unlink(filename);
- if (fetch_pack(sha1))
- return error("Tried %s", url);
- return 0;
+ return -1;
}
close(local);
@@ -291,11 +371,30 @@ int fetch(unsigned char *sha1)
return 0;
}
+int fetch(unsigned char *sha1)
+{
+ struct alt_base *altbase = alt;
+ while (altbase) {
+ if (!fetch_object(altbase, sha1))
+ return 0;
+ if (!fetch_pack(altbase, sha1))
+ return 0;
+ if (fetch_alternates(altbase->base) > 0) {
+ altbase = alt;
+ continue;
+ }
+ altbase = altbase->next;
+ }
+ return error("Unable to find %s under %s\n", sha1_to_hex(sha1),
+ initial_base);
+}
+
int fetch_ref(char *ref, unsigned char *sha1)
{
char *url, *posn;
char hex[42];
struct buffer buffer;
+ char *base = initial_base;
buffer.size = 41;
buffer.posn = 0;
buffer.buffer = hex;
@@ -303,6 +402,7 @@ int fetch_ref(char *ref, unsigned char *sha1)
curl_easy_setopt(curl, CURLOPT_FILE, &buffer);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fwrite_buffer);
+ curl_easy_setopt(curl, CURLOPT_HTTPHEADER, NULL);
url = xmalloc(strlen(base) + 6 + strlen(ref));
strcpy(url, base);
@@ -354,6 +454,7 @@ int main(int argc, char **argv)
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
+ no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
curl_ssl_verify = getenv("GIT_SSL_NO_VERIFY") ? 0 : 1;
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, curl_ssl_verify);
@@ -361,11 +462,17 @@ int main(int argc, char **argv)
curl_easy_setopt(curl, CURLOPT_NETRC, CURL_NETRC_OPTIONAL);
#endif
- base = url;
+ alt = xmalloc(sizeof(*alt));
+ alt->base = url;
+ alt->got_indices = 0;
+ alt->packs = NULL;
+ alt->next = NULL;
+ initial_base = url;
if (pull(commit_id))
return 1;
+ curl_slist_free_all(no_pragma_header);
curl_global_cleanup();
return 0;
}
diff --git a/ident.c b/ident.c
index 0df2d97..a2d241f 100644
--- a/ident.c
+++ b/ident.c
@@ -36,13 +36,11 @@ int setup_ident(void)
memcpy(real_email, pw->pw_name, len);
real_email[len++] = '@';
gethostname(real_email + len, sizeof(real_email) - len);
-#ifndef NO_GETDOMAINNAME
if (!strchr(real_email+len, '.')) {
len = strlen(real_email);
real_email[len++] = '.';
getdomainname(real_email+len, sizeof(real_email)-len);
}
-#endif
/* And set the default date */
datestamp(real_date, sizeof(real_date));
return 0;
diff --git a/object.c b/object.c
index 63e6e78..1fdebe0 100644
--- a/object.c
+++ b/object.c
@@ -9,6 +9,8 @@ struct object **objs;
int nr_objs;
static int obj_allocs;
+int track_object_refs = 1;
+
static int find_object(const unsigned char *sha1)
{
int first = 0, last = nr_objs;
@@ -67,9 +69,12 @@ void created_object(const unsigned char *sha1, struct object *obj)
void add_ref(struct object *refer, struct object *target)
{
- struct object_list **pp = &refer->refs;
- struct object_list *p;
-
+ struct object_list **pp, *p;
+
+ if (!track_object_refs)
+ return;
+
+ pp = &refer->refs;
while ((p = *pp) != NULL) {
if (p->item == target)
return;
@@ -87,6 +92,8 @@ void mark_reachable(struct object *obj, unsigned int mask)
{
struct object_list *p = obj->refs;
+ if (!track_object_refs)
+ die("cannot do reachability with object refs turned off");
/* If we've been here already, don't bother */
if (obj->flags & mask)
return;
diff --git a/object.h b/object.h
index bf74449..6accda3 100644
--- a/object.h
+++ b/object.h
@@ -17,6 +17,7 @@ struct object {
void *util;
};
+extern int track_object_refs;
extern int nr_objs;
extern struct object **objs;
diff --git a/rev-cache.c b/rev-cache.c
deleted file mode 100644
index 6344d62..0000000
--- a/rev-cache.c
+++ /dev/null
@@ -1,318 +0,0 @@
-#include "refs.h"
-#include "cache.h"
-#include "rev-cache.h"
-
-struct rev_cache **rev_cache;
-int nr_revs, alloc_revs;
-
-static struct rev_list_elem *rle_free;
-
-#define BATCH_SIZE 512
-
-int find_rev_cache(const unsigned char *sha1)
-{
- int lo = 0, hi = nr_revs;
- while (lo < hi) {
- int mi = (lo + hi) / 2;
- struct rev_cache *ri = rev_cache[mi];
- int cmp = memcmp(sha1, ri->sha1, 20);
- if (!cmp)
- return mi;
- if (cmp < 0)
- hi = mi;
- else
- lo = mi + 1;
- }
- return -lo - 1;
-}
-
-static struct rev_list_elem *alloc_list_elem(void)
-{
- struct rev_list_elem *rle;
- if (!rle_free) {
- int i;
-
- rle = xmalloc(sizeof(*rle) * BATCH_SIZE);
- for (i = 0; i < BATCH_SIZE - 1; i++) {
- rle[i].ri = NULL;
- rle[i].next = &rle[i + 1];
- }
- rle[BATCH_SIZE - 1].ri = NULL;
- rle[BATCH_SIZE - 1].next = NULL;
- rle_free = rle;
- }
- rle = rle_free;
- rle_free = rle->next;
- return rle;
-}
-
-static struct rev_cache *create_rev_cache(const unsigned char *sha1)
-{
- struct rev_cache *ri;
- int pos = find_rev_cache(sha1);
-
- if (0 <= pos)
- return rev_cache[pos];
- pos = -pos - 1;
- if (alloc_revs <= ++nr_revs) {
- alloc_revs = alloc_nr(alloc_revs);
- rev_cache = xrealloc(rev_cache, sizeof(ri) * alloc_revs);
- }
- if (pos < nr_revs)
- memmove(rev_cache + pos + 1, rev_cache + pos,
- (nr_revs - pos - 1) * sizeof(ri));
- ri = xcalloc(1, sizeof(*ri));
- memcpy(ri->sha1, sha1, 20);
- rev_cache[pos] = ri;
- return ri;
-}
-
-static unsigned char last_sha1[20];
-
-static void write_one_rev_cache(FILE *rev_cache_file, struct rev_cache *ri)
-{
- unsigned char flag;
- struct rev_list_elem *rle;
-
- if (ri->written)
- return;
-
- if (ri->parsed) {
- /* We use last_sha1 compression only for the first parent;
- * otherwise the resulting rev-cache would lose the parent
- * order information.
- */
- if (ri->parents &&
- !memcmp(ri->parents->ri->sha1, last_sha1, 20))
- flag = (ri->num_parents - 1) | 0x80;
- else
- flag = ri->num_parents;
-
- fwrite(ri->sha1, 20, 1, rev_cache_file);
- fwrite(&flag, 1, 1, rev_cache_file);
- for (rle = ri->parents; rle; rle = rle->next) {
- if (flag & 0x80 && rle == ri->parents)
- continue;
- fwrite(rle->ri->sha1, 20, 1, rev_cache_file);
- }
- memcpy(last_sha1, ri->sha1, 20);
- ri->written = 1;
- }
- /* recursively write children depth first */
- for (rle = ri->children; rle; rle = rle->next)
- write_one_rev_cache(rev_cache_file, rle->ri);
-}
-
-void write_rev_cache(const char *newpath, const char *oldpath)
-{
- /* write the following commit ancestry information in
- * $GIT_DIR/info/rev-cache.
- *
- * The format is:
- * 20-byte SHA1 (commit ID)
- * 1-byte flag:
- * - bit 0-6 records "number of parent commit SHA1s to
- * follow" (i.e. up to 127 children can be listed).
- * - when the bit 7 is on, then "the entry immediately
- * before this entry is one of the parents of this
- * commit".
- * N x 20-byte SHA1 (parent commit IDs)
- */
- FILE *rev_cache_file;
- int i;
- struct rev_cache *ri;
-
- if (!strcmp(newpath, oldpath)) {
- /* If we are doing it in place */
- rev_cache_file = fopen(newpath, "a");
- }
- else {
- char buf[8096];
- size_t sz;
- FILE *oldfp = fopen(oldpath, "r");
- rev_cache_file = fopen(newpath, "w");
- if (oldfp) {
- while (1) {
- sz = fread(buf, 1, sizeof(buf), oldfp);
- if (sz == 0)
- break;
- fwrite(buf, 1, sz, rev_cache_file);
- }
- fclose(oldfp);
- }
- }
-
- memset(last_sha1, 0, 20);
-
- /* Go through available rev_cache structures, starting from
- * parentless ones first, so that we would get most out of
- * last_sha1 optimization by the depth first behaviour of
- * write_one_rev_cache().
- */
- for (i = 0; i < nr_revs; i++) {
- ri = rev_cache[i];
- if (ri->num_parents)
- continue;
- write_one_rev_cache(rev_cache_file, ri);
- }
- /* Then the rest */
- for (i = 0; i < nr_revs; i++) {
- ri = rev_cache[i];
- write_one_rev_cache(rev_cache_file, ri);
- }
- fclose(rev_cache_file);
-}
-
-static void add_parent(struct rev_cache *child,
- const unsigned char *parent_sha1)
-{
- struct rev_cache *parent = create_rev_cache(parent_sha1);
- struct rev_list_elem *e = alloc_list_elem();
-
- /* Keep the parent list ordered in the same way the commit
- * object records them.
- */
- e->ri = parent;
- e->next = NULL;
- if (!child->parents_tail)
- child->parents = e;
- else
- child->parents_tail->next = e;
- child->parents_tail = e;
- child->num_parents++;
-
- /* There is no inherent order of the children so we just
- * LIFO them together.
- */
- e = alloc_list_elem();
- e->next = parent->children;
- parent->children = e;
- e->ri = child;
- parent->num_children++;
-}
-
-int read_rev_cache(const char *path, FILE *dumpfile, int dry_run)
-{
- unsigned char *map;
- int fd;
- struct stat st;
- unsigned long ofs, len;
- struct rev_cache *ri = NULL;
-
- fd = open(path, O_RDONLY);
- if (fd < 0) {
- if (dry_run)
- return error("cannot open %s", path);
- if (errno == ENOENT)
- return 0;
- return -1;
- }
- if (fstat(fd, &st)) {
- close(fd);
- return -1;
- }
- map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
- close(fd);
- if (map == MAP_FAILED)
- return -1;
-
- memset(last_sha1, 0, 20);
- ofs = 0;
- len = st.st_size;
- while (ofs < len) {
- unsigned char sha1[20];
- int flag, cnt, i;
- if (len < ofs + 21)
- die("rev-cache too short");
- memcpy(sha1, map + ofs, 20);
- flag = map[ofs + 20];
- ofs += 21;
- cnt = (flag & 0x7f) + ((flag & 0x80) != 0);
- if (len < ofs + (flag & 0x7f) * 20)
- die("rev-cache too short to have %d more parents",
- (flag & 0x7f));
- if (dumpfile)
- fprintf(dumpfile, "%s", sha1_to_hex(sha1));
- if (!dry_run) {
- ri = create_rev_cache(sha1);
- if (!ri)
- die("cannot create rev-cache for %s",
- sha1_to_hex(sha1));
- ri->written = ri->parsed = 1;
- }
- i = 0;
- if (flag & 0x80) {
- if (!dry_run)
- add_parent(ri, last_sha1);
- if (dumpfile)
- fprintf(dumpfile, " %s",
- sha1_to_hex(last_sha1));
- i++;
- }
- while (i++ < cnt) {
- if (!dry_run)
- add_parent(ri, map + ofs);
- if (dumpfile)
- fprintf(dumpfile, " %s",
- sha1_to_hex(last_sha1));
- ofs += 20;
- }
- if (dumpfile)
- fprintf(dumpfile, "\n");
- memcpy(last_sha1, sha1, 20);
- }
- if (ofs != len)
- die("rev-cache truncated?");
- munmap(map, len);
- return 0;
-}
-
-int record_rev_cache(const unsigned char *sha1, FILE *dumpfile)
-{
- unsigned char parent[20];
- char type[20];
- unsigned long size, ofs;
- unsigned int cnt, i;
- void *buf;
- struct rev_cache *ri;
-
- buf = read_sha1_file(sha1, type, &size);
- if (!buf)
- return error("%s: not found", sha1_to_hex(sha1));
- if (strcmp(type, "commit")) {
- free(buf);
- return error("%s: not a commit but a %s",
- sha1_to_hex(sha1), type);
- }
- ri = create_rev_cache(sha1);
- if (ri->parsed)
- return 0;
- if (dumpfile)
- fprintf(dumpfile, "commit %s\n", sha1_to_hex(sha1));
-
- cnt = 0;
- ofs = 46; /* "tree " + hex-sha1 + "\n" */
- while (!memcmp(buf + ofs, "parent ", 7) &&
- !get_sha1_hex(buf + ofs + 7, parent)) {
- ofs += 48;
- cnt++;
- }
- if (cnt * 48 + 46 != ofs) {
- free(buf);
- die("internal error in record_rev_cache");
- }
-
- ri = create_rev_cache(sha1);
- ri->parsed = 1;
-
- for (i = 0; i < cnt; i++) {
- unsigned char parent_sha1[20];
-
- ofs = 46 + i * 48 + 7;
- get_sha1_hex(buf + ofs, parent_sha1);
- add_parent(ri, parent_sha1);
- record_rev_cache(parent_sha1, dumpfile);
- }
- free(buf);
- return 0;
-}
diff --git a/rev-cache.h b/rev-cache.h
deleted file mode 100644
index b238ac6..0000000
--- a/rev-cache.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef REV_CACHE_H
-#define REV_CACHE_H
-
-extern struct rev_cache {
- struct rev_cache *head_list;
- struct rev_list_elem *children;
- struct rev_list_elem *parents;
- struct rev_list_elem *parents_tail;
- unsigned short num_parents;
- unsigned short num_children;
- unsigned int written : 1;
- unsigned int parsed : 1;
- unsigned int work : 30;
- void *work_ptr;
- unsigned char sha1[20];
-} **rev_cache;
-extern int nr_revs, alloc_revs;
-
-struct rev_list_elem {
- struct rev_list_elem *next;
- struct rev_cache *ri;
-};
-
-extern int find_rev_cache(const unsigned char *);
-extern int read_rev_cache(const char *, FILE *, int);
-extern int record_rev_cache(const unsigned char *, FILE *);
-extern void write_rev_cache(const char *new, const char *old);
-
-#endif
diff --git a/rev-list.c b/rev-list.c
index 2d97cdb..e41d5a0 100644
--- a/rev-list.c
+++ b/rev-list.c
@@ -147,11 +147,16 @@ static struct object_list **process_tree(struct tree *tree, struct object_list *
die("bad tree object %s", sha1_to_hex(obj->sha1));
obj->flags |= SEEN;
p = add_object(obj, p, name);
- for (entry = tree->entries ; entry ; entry = entry->next) {
+ entry = tree->entries;
+ tree->entries = NULL;
+ while (entry) {
+ struct tree_entry_list *next = entry->next;
if (entry->directory)
p = process_tree(entry->item.tree, p, entry->name);
else
p = process_blob(entry->item.blob, p, entry->name);
+ free(entry);
+ entry = next;
}
return p;
}
@@ -218,12 +223,15 @@ static void mark_tree_uninteresting(struct tree *tree)
if (parse_tree(tree) < 0)
die("bad tree %s", sha1_to_hex(obj->sha1));
entry = tree->entries;
+ tree->entries = NULL;
while (entry) {
+ struct tree_entry_list *next = entry->next;
if (entry->directory)
mark_tree_uninteresting(entry->item.tree);
else
mark_blob_uninteresting(entry->item.blob);
- entry = entry->next;
+ free(entry);
+ entry = next;
}
}
@@ -231,8 +239,6 @@ static void mark_parents_uninteresting(struct commit *commit)
{
struct commit_list *parents = commit->parents;
- if (tree_objects)
- mark_tree_uninteresting(commit->tree);
while (parents) {
struct commit *commit = parents->item;
commit->object.flags |= UNINTERESTING;
@@ -272,29 +278,6 @@ static int everybody_uninteresting(struct commit_list *orig)
continue;
return 0;
}
-
- /*
- * Ok, go back and mark all the edge trees uninteresting,
- * since otherwise we can have situations where a parent
- * that was marked uninteresting (and we never even had
- * to look at) had lots of objects that we don't want to
- * include.
- *
- * NOTE! This still doesn't mean that the object list is
- * "correct", since we may end up listing objects that
- * even older commits (that we don't list) do actually
- * reference, but it gets us to a minimal list (or very
- * close) in practice.
- */
- if (!tree_objects)
- return 1;
-
- while (orig) {
- struct commit *commit = orig->item;
- if (!parse_commit(commit) && commit->tree)
- mark_tree_uninteresting(commit->tree);
- orig = orig->next;
- }
return 1;
}
@@ -370,6 +353,19 @@ static struct commit_list *find_bisection(struct commit_list *list)
return best;
}
+static void mark_edges_uninteresting(struct commit_list *list)
+{
+ for ( ; list; list = list->next) {
+ struct commit_list *parents = list->item->parents;
+
+ for ( ; parents; parents = parents->next) {
+ struct commit *commit = parents->item;
+ if (commit->object.flags & UNINTERESTING)
+ mark_tree_uninteresting(commit->tree);
+ }
+ }
+}
+
static struct commit_list *limit_list(struct commit_list *list)
{
struct commit_list *newlist = NULL;
@@ -388,6 +384,8 @@ static struct commit_list *limit_list(struct commit_list *list)
}
p = &commit_list_insert(commit, p)->next;
}
+ if (tree_objects)
+ mark_edges_uninteresting(newlist);
if (bisect_list)
newlist = find_bisection(newlist);
return newlist;
@@ -563,6 +561,8 @@ int main(int argc, char **argv)
struct commit *exclude = NULL;
struct commit *include = NULL;
*dotdot = 0;
+ if (!*next)
+ next = "HEAD";
exclude = get_commit_reference(arg, UNINTERESTING);
include = get_commit_reference(next, 0);
if (exclude && include) {
@@ -571,7 +571,7 @@ int main(int argc, char **argv)
handle_one_commit(include, &list);
continue;
}
- *next = '.';
+ *dotdot = '.';
}
if (*arg == '^') {
flags = UNINTERESTING;
@@ -582,6 +582,9 @@ int main(int argc, char **argv)
handle_one_commit(commit, &list);
}
+ save_commit_buffer = verbose_header;
+ track_object_refs = 0;
+
if (!merge_order) {
sort_by_date(&list);
if (limited)
diff --git a/rsh.c b/rsh.c
index 04cbdf7..1c63686 100644
--- a/rsh.c
+++ b/rsh.c
@@ -8,6 +8,71 @@
#define COMMAND_SIZE 4096
+/*
+ * Write a shell-quoted version of a string into a buffer, and
+ * return bytes that ought to be output excluding final null.
+ */
+static int shell_quote(char *buf, int nmax, const char *str)
+{
+ char ch;
+ int nq;
+ int oc = 0;
+
+ while ( (ch = *str++) ) {
+ nq = 0;
+ if ( strchr(" !\"#$%&\'()*;<=>?[\\]^`{|}", ch) )
+ nq = 1;
+
+ if ( nq ) {
+ if ( nmax > 1 ) {
+ *buf++ = '\\';
+ nmax--;
+ }
+ oc++;
+ }
+
+ if ( nmax > 1 ) {
+ *buf++ = ch;
+ nmax--;
+ }
+ oc++;
+ }
+
+ if ( nmax )
+ *buf = '\0';
+
+ return oc;
+}
+
+/*
+ * Append a string to a string buffer, with or without quoting. Return true
+ * if the buffer overflowed.
+ */
+static int add_to_string(char **ptrp, int *sizep, const char *str, int quote)
+{
+ char *p = *ptrp;
+ int size = *sizep;
+ int oc;
+
+ if ( quote ) {
+ oc = shell_quote(p, size, str);
+ } else {
+ oc = strlen(str);
+ memcpy(p, str, (oc >= size) ? size-1 : oc);
+ }
+
+ if ( oc >= size ) {
+ p[size-1] = '\0';
+ *ptrp += size-1;
+ *sizep = 1;
+ return 1; /* Overflow, string unusable */
+ }
+
+ *ptrp += oc;
+ *sizep -= oc;
+ return 0;
+}
+
int setup_connection(int *fd_in, int *fd_out, const char *remote_prog,
char *url, int rmt_argc, char **rmt_argv)
{
@@ -16,6 +81,8 @@ int setup_connection(int *fd_in, int *fd_out, const char *remote_prog,
int sv[2];
char command[COMMAND_SIZE];
char *posn;
+ int sizen;
+ int of;
int i;
if (!strcmp(url, "-")) {
@@ -37,24 +104,30 @@ int setup_connection(int *fd_in, int *fd_out, const char *remote_prog,
if (!path) {
return error("Bad URL: %s", url);
}
- /* ssh <host> 'cd <path>; stdio-pull <arg...> <commit-id>' */
- snprintf(command, COMMAND_SIZE,
- "%s='%s' %s",
- GIT_DIR_ENVIRONMENT, path, remote_prog);
- *path = '\0';
- posn = command + strlen(command);
- for (i = 0; i < rmt_argc; i++) {
- *(posn++) = ' ';
- strncpy(posn, rmt_argv[i], COMMAND_SIZE - (posn - command));
- posn += strlen(rmt_argv[i]);
- if (posn - command + 4 >= COMMAND_SIZE) {
- return error("Command line too long");
- }
+ /* $GIT_RSH <host> "env GIR_DIR=<path> <remote_prog> <args...>" */
+ sizen = COMMAND_SIZE;
+ posn = command;
+ of = 0;
+ of |= add_to_string(&posn, &sizen, "env ", 0);
+ of |= add_to_string(&posn, &sizen, GIT_DIR_ENVIRONMENT, 0);
+ of |= add_to_string(&posn, &sizen, "=", 0);
+ of |= add_to_string(&posn, &sizen, path, 1);
+ of |= add_to_string(&posn, &sizen, " ", 0);
+ of |= add_to_string(&posn, &sizen, remote_prog, 1);
+
+ for ( i = 0 ; i < rmt_argc ; i++ ) {
+ of |= add_to_string(&posn, &sizen, " ", 0);
+ of |= add_to_string(&posn, &sizen, rmt_argv[i], 1);
}
- strcpy(posn, " -");
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv)) {
+
+ of |= add_to_string(&posn, &sizen, " -", 0);
+
+ if ( of )
+ return error("Command line too long");
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv))
return error("Couldn't create socket");
- }
+
if (!fork()) {
const char *ssh, *ssh_basename;
ssh = getenv("GIT_SSH");
diff --git a/server-info.c b/server-info.c
index 2b3aeca..a9e5607 100644
--- a/server-info.c
+++ b/server-info.c
@@ -3,20 +3,9 @@
#include "object.h"
#include "commit.h"
#include "tag.h"
-#include "rev-cache.h"
/* refs */
static FILE *info_ref_fp;
-static unsigned long info_ref_time;
-static int info_ref_is_stale = 0;
-
-static int stat_ref(const char *path, const unsigned char *sha1)
-{
- struct stat st;
- if (!stat(path, &st) && info_ref_time < st.st_mtime)
- info_ref_is_stale = 1;
- return 0;
-}
static int add_info_ref(const char *path, const unsigned char *sha1)
{
@@ -26,7 +15,6 @@ static int add_info_ref(const char *path, const unsigned char *sha1)
static int update_info_refs(int force)
{
- struct stat st;
char *path0 = strdup(git_path("info/refs"));
int len = strlen(path0);
char *path1 = xmalloc(len + 2);
@@ -34,21 +22,6 @@ static int update_info_refs(int force)
strcpy(path1, path0);
strcpy(path1 + len, "+");
- if (!force) {
- if (stat(path0, &st)) {
- if (errno == ENOENT)
- info_ref_is_stale = 1;
- else
- return error("cannot stat %s", path0);
- }
- else {
- info_ref_time = st.st_mtime;
- for_each_ref(stat_ref);
- }
- if (!info_ref_is_stale)
- return 0;
- }
-
safe_create_leading_directories(path0);
info_ref_fp = fopen(path1, "w");
if (!info_ref_fp)
@@ -516,45 +489,6 @@ static int update_info_packs(int force)
return 0;
}
-/* rev-cache */
-static int record_rev_cache_ref(const char *path, const unsigned char *sha1)
-{
- struct object *obj = parse_object(sha1);
-
- if (!obj)
- return error("ref %s has bad sha %s", path, sha1_to_hex(sha1));
- while (obj && obj->type == tag_type)
- obj = parse_object(((struct tag *)obj)->tagged->sha1);
- if (!obj || obj->type != commit_type)
- /* tag pointing at a non-commit */
- return 0;
- return record_rev_cache(obj->sha1, NULL);
-}
-
-static int update_info_revs(int force)
-{
- char *path0 = strdup(git_path("info/rev-cache"));
- int len = strlen(path0);
- char *path1 = xmalloc(len + 2);
-
- strcpy(path1, path0);
- strcpy(path1 + len, "+");
-
- /* read existing rev-cache */
- if (!force)
- read_rev_cache(path0, NULL, 0);
- safe_create_leading_directories(path0);
-
- for_each_ref(record_rev_cache_ref);
-
- /* update the rev-cache database */
- write_rev_cache(path1, force ? "/dev/null" : path0);
- rename(path1, path0);
- free(path1);
- free(path0);
- return 0;
-}
-
/* public */
int update_server_info(int force)
{
@@ -566,7 +500,6 @@ int update_server_info(int force)
errs = errs | update_info_refs(force);
errs = errs | update_info_packs(force);
- errs = errs | update_info_revs(force);
return errs;
}
diff --git a/show-rev-cache.c b/show-rev-cache.c
deleted file mode 100644
index fa92b87..0000000
--- a/show-rev-cache.c
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "cache.h"
-#include "rev-cache.h"
-
-static char *show_rev_cache_usage =
-"git-show-rev-cache <rev-cache-file>";
-
-int main(int ac, char **av)
-{
- while (1 < ac && av[0][1] == '-') {
- /* do flags here */
- break;
- ac--; av++;
- }
- if (ac != 2)
- usage(show_rev_cache_usage);
-
- return read_rev_cache(av[1], stdout, 1);
-}
diff --git a/ssh-fetch.c b/ssh-fetch.c
index d8f4368..683a1e4 100644
--- a/ssh-fetch.c
+++ b/ssh-fetch.c
@@ -1,3 +1,13 @@
+#ifndef COUNTERPART_ENV_NAME
+#define COUNTERPART_ENV_NAME "GIT_SSH_UPLOAD"
+#endif
+#ifndef COUNTERPART_PROGRAM_NAME
+#define COUNTERPART_PROGRAM_NAME "git-ssh-upload"
+#endif
+#ifndef MY_PROGRAM_NAME
+#define MY_PROGRAM_NAME "git-ssh-fetch"
+#endif
+
#include "cache.h"
#include "commit.h"
#include "rsh.h"
@@ -82,6 +92,9 @@ int fetch_ref(char *ref, unsigned char *sha1)
return 0;
}
+static const char ssh_fetch_usage[] =
+ MY_PROGRAM_NAME
+ " [-c] [-t] [-a] [-v] [-d] [--recover] [-w ref] commit-id url";
int main(int argc, char **argv)
{
char *commit_id;
@@ -110,7 +123,7 @@ int main(int argc, char **argv)
arg++;
}
if (argc < arg + 2) {
- usage("git-ssh-fetch [-c] [-t] [-a] [-v] [-d] [--recover] [-w ref] commit-id url");
+ usage(ssh_fetch_usage);
return 1;
}
commit_id = argv[arg];
diff --git a/ssh-pull.c b/ssh-pull.c
new file mode 100644
index 0000000..868ce4d
--- /dev/null
+++ b/ssh-pull.c
@@ -0,0 +1,4 @@
+#define COUNTERPART_ENV_NAME "GIT_SSH_PUSH"
+#define COUNTERPART_PROGRAM_NAME "git-ssh-push"
+#define MY_PROGRAM_NAME "git-ssh-pull"
+#include "ssh-fetch.c"
diff --git a/ssh-push.c b/ssh-push.c
new file mode 100644
index 0000000..a562df1
--- /dev/null
+++ b/ssh-push.c
@@ -0,0 +1,4 @@
+#define COUNTERPART_ENV_NAME "GIT_SSH_PULL"
+#define COUNTERPART_PROGRAM_NAME "git-ssh-pull"
+#define MY_PROGRAM_NAME "git-ssh-push"
+#include "ssh-upload.c"
diff --git a/ssh-upload.c b/ssh-upload.c
index 10a3687..603abcc 100644
--- a/ssh-upload.c
+++ b/ssh-upload.c
@@ -1,3 +1,13 @@
+#ifndef COUNTERPART_ENV_NAME
+#define COUNTERPART_ENV_NAME "GIT_SSH_FETCH"
+#endif
+#ifndef COUNTERPART_PROGRAM_NAME
+#define COUNTERPART_PROGRAM_NAME "git-ssh-fetch"
+#endif
+#ifndef MY_PROGRAM_NAME
+#define MY_PROGRAM_NAME "git-ssh-upload"
+#endif
+
#include "cache.h"
#include "rsh.h"
#include "refs.h"
@@ -97,7 +107,7 @@ static void service(int fd_in, int fd_out) {
}
static const char ssh_push_usage[] =
- "git-ssh-upload [-c] [-t] [-a] [-w ref] commit-id url";
+ MY_PROGRAM_NAME " [-c] [-t] [-a] [-w ref] commit-id url";
int main(int argc, char **argv)
{
@@ -109,8 +119,8 @@ int main(int argc, char **argv)
unsigned char sha1[20];
char hex[41];
- prog = getenv("GIT_SSH_PULL");
- if (!prog) prog = "git-ssh-fetch";
+ prog = getenv(COUNTERPART_ENV_NAME);
+ if (!prog) prog = COUNTERPART_PROGRAM_NAME;
while (arg < argc && argv[arg][0] == '-') {
if (argv[arg][1] == 'w')
arg++;
diff --git a/t/t1001-read-tree-m-2way.sh b/t/t1001-read-tree-m-2way.sh
index 5b69681..d0ed242 100755
--- a/t/t1001-read-tree-m-2way.sh
+++ b/t/t1001-read-tree-m-2way.sh
@@ -11,7 +11,7 @@ There is the head (called H) and another commit (called M), which is
simply ahead of H. The index and the work tree contains a state that
is derived from H, but may also have local changes. This test checks
all the combinations described in the two-tree merge "carry forward"
-rules, found in <Documentation/git-rev-tree.txt>.
+rules, found in <Documentation/git-read-tree.txt>.
In the test, these paths are used:
bozbar - in H, stays in M, modified from bozbar to gnusto