mirror of
https://github.com/git/git
synced 2024-08-27 19:49:21 +00:00
Merge branch 'master' of .
This commit is contained in:
commit
8ac93bc98f
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
------
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
@ -38,8 +38,6 @@ of what they are for:
|
|||
|
||||
* info/refs
|
||||
|
||||
* info/rev-cache
|
||||
|
||||
|
||||
BUGS
|
||||
----
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
24
Makefile
24
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:
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
4
commit.c
4
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;
|
||||
}
|
||||
|
|
1
commit.h
1
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);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#define _XOPEN_SOURCE /* glibc2 needs this */
|
||||
#define __EXTENSIONS__ /* solaris needs this */
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include "cache.h"
|
||||
|
|
4
debian/control
vendored
4
debian/control
vendored
|
@ -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
|
||||
|
|
2
debian/rules
vendored
2
debian/rules
vendored
|
@ -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:
|
||||
|
|
|
@ -370,6 +370,7 @@ static int diff_tree_commit(const unsigned char *commit, const char *name)
|
|||
}
|
||||
offset += 48;
|
||||
}
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
24
diff.c
24
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
100
fetch.c
100
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);
|
||||
|
|
|
@ -110,7 +110,7 @@ bisect_next_check() {
|
|||
}
|
||||
|
||||
bisect_auto_next() {
|
||||
bisect_next_check && bisect_next
|
||||
bisect_next_check && bisect_next || :
|
||||
}
|
||||
|
||||
bisect_next() {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
28
git-clone.sh
28
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"
|
||||
|
|
|
@ -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
|
||||
|
|
24
git-fetch.sh
24
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
|
||||
}
|
||||
;;
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
'')
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ sub changelog_input {
|
|||
if ($pstate == 1) {
|
||||
my ($email);
|
||||
|
||||
next unless /^Author: (.*)<(.*)>.*$/;
|
||||
next unless /^[Aa]uthor:? (.*)<(.*)>.*$/;
|
||||
|
||||
$n_records++;
|
||||
|
||||
|
|
177
http-fetch.c
177
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 int got_alternates = 0;
|
||||
|
||||
static struct packed_git *packs = NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
2
ident.c
2
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;
|
||||
|
|
13
object.c
13
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;
|
||||
|
|
1
object.h
1
object.h
|
@ -17,6 +17,7 @@ struct object {
|
|||
void *util;
|
||||
};
|
||||
|
||||
extern int track_object_refs;
|
||||
extern int nr_objs;
|
||||
extern struct object **objs;
|
||||
|
||||
|
|
318
rev-cache.c
318
rev-cache.c
|
@ -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;
|
||||
}
|
29
rev-cache.h
29
rev-cache.h
|
@ -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
|
59
rev-list.c
59
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)
|
||||
|
|
105
rsh.c
105
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");
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
15
ssh-fetch.c
15
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];
|
||||
|
|
4
ssh-pull.c
Normal file
4
ssh-pull.c
Normal file
|
@ -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"
|
4
ssh-push.c
Normal file
4
ssh-push.c
Normal file
|
@ -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"
|
16
ssh-upload.c
16
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++;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue