Merge branch 'jc/fsck' into next

* jc/fsck:
  fsck-objects: Remove --standalone
  refs.c::do_for_each_ref(): Finish error message lines with "\n"
  Nicer output from 'git'
  Use #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
  Remove trailing dot after short description
  Fix some inconsistencies in the docs
  contrib/git-svn: fix a harmless warning on rebuild (with old repos)
  contrib/git-svn: remove the --no-stop-on-copy flag
  contrib/git-svn: fix svn compat and fetch args
  Don't recurse into parents marked uninteresting.
  diff-delta: bound hash list length to avoid O(m*n) behavior
  test-delta needs zlib to compile
  git-fmt-merge-msg cleanup
This commit is contained in:
Junio C Hamano 2006-03-09 13:10:50 -08:00
commit b8cfe290a8
72 changed files with 341 additions and 186 deletions

1
.gitignore vendored
View File

@ -121,6 +121,7 @@ git-write-tree
git-core-*/?* git-core-*/?*
test-date test-date
test-delta test-delta
common-cmds.h
*.tar.gz *.tar.gz
*.dsc *.dsc
*.deb *.deb

View File

@ -3,7 +3,7 @@ git-add(1)
NAME NAME
---- ----
git-add - Add files to the index file. git-add - Add files to the index file
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-applypatch(1)
NAME NAME
---- ----
git-applypatch - Apply one patch extracted from an e-mail. git-applypatch - Apply one patch extracted from an e-mail
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-branch(1)
NAME NAME
---- ----
git-branch - Create a new branch, or remove an old one. git-branch - Create a new branch, or remove an old one
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-check-ref-format(1)
NAME NAME
---- ----
git-check-ref-format - Make sure ref name is well formed. git-check-ref-format - Make sure ref name is well formed
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-checkout(1)
NAME NAME
---- ----
git-checkout - Checkout and switch to a branch. git-checkout - Checkout and switch to a branch
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-cherry-pick(1)
NAME NAME
---- ----
git-cherry-pick - Apply the change introduced by an existing commit. git-cherry-pick - Apply the change introduced by an existing commit
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-cherry(1)
NAME NAME
---- ----
git-cherry - Find commits not merged upstream. git-cherry - Find commits not merged upstream
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-clone-pack(1)
NAME NAME
---- ----
git-clone-pack - Clones a repository by receiving packed objects. git-clone-pack - Clones a repository by receiving packed objects
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-clone(1)
NAME NAME
---- ----
git-clone - Clones a repository. git-clone - Clones a repository
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-count-objects(1)
NAME NAME
---- ----
git-count-objects - Reports on unpacked objects. git-count-objects - Reports on unpacked objects
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-daemon(1)
NAME NAME
---- ----
git-daemon - A really simple server for git repositories. git-daemon - A really simple server for git repositories
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-describe(1)
NAME NAME
---- ----
git-describe - Show the most recent tag that is reachable from a commit. git-describe - Show the most recent tag that is reachable from a commit
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-diff-stages(1)
NAME NAME
---- ----
git-diff-stages - Compares content and mode of blobs between stages in an unmerged index file. git-diff-stages - Compares content and mode of blobs between stages in an unmerged index file
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-diff(1)
NAME NAME
---- ----
git-diff - Show changes between commits, commit and working tree, etc. git-diff - Show changes between commits, commit and working tree, etc
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-fetch-pack(1)
NAME NAME
---- ----
git-fetch-pack - Receive missing objects from another repository. git-fetch-pack - Receive missing objects from another repository
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-fetch(1)
NAME NAME
---- ----
git-fetch - Download objects and a head from another repository. git-fetch - Download objects and a head from another repository
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-format-patch(1)
NAME NAME
---- ----
git-format-patch - Prepare patches for e-mail submission. git-format-patch - Prepare patches for e-mail submission
SYNOPSIS SYNOPSIS

View File

@ -10,7 +10,7 @@ SYNOPSIS
-------- --------
[verse] [verse]
'git-fsck-objects' [--tags] [--root] [--unreachable] [--cache] 'git-fsck-objects' [--tags] [--root] [--unreachable] [--cache]
[--standalone | --full] [--strict] [<object>*] [--full] [--strict] [<object>*]
DESCRIPTION DESCRIPTION
----------- -----------
@ -38,21 +38,14 @@ index file and all SHA1 references in .git/refs/* as heads.
Consider any object recorded in the index also as a head node for Consider any object recorded in the index also as a head node for
an unreachability trace. an unreachability trace.
--standalone::
Limit checks to the contents of GIT_OBJECT_DIRECTORY
($GIT_DIR/objects), making sure that it is consistent and
complete without referring to objects found in alternate
object pools listed in GIT_ALTERNATE_OBJECT_DIRECTORIES,
nor packed git archives found in $GIT_DIR/objects/pack;
cannot be used with --full.
--full:: --full::
Check not just objects in GIT_OBJECT_DIRECTORY Check not just objects in GIT_OBJECT_DIRECTORY
($GIT_DIR/objects), but also the ones found in alternate ($GIT_DIR/objects), but also the ones found in alternate
object pools listed in GIT_ALTERNATE_OBJECT_DIRECTORIES, object pools listed in GIT_ALTERNATE_OBJECT_DIRECTORIES
or $GIT_DIR/objects/info/alternates,
and in packed git archives found in $GIT_DIR/objects/pack and in packed git archives found in $GIT_DIR/objects/pack
and corresponding pack subdirectories in alternate and corresponding pack subdirectories in alternate
object pools; cannot be used with --standalone. object pools.
--strict:: --strict::
Enable more strict checking, namely to catch a file mode Enable more strict checking, namely to catch a file mode

View File

@ -3,7 +3,7 @@ git-get-tar-commit-id(1)
NAME NAME
---- ----
git-get-tar-commit-id - Extract commit ID from an archive created using git-tar-tree. git-get-tar-commit-id - Extract commit ID from an archive created using git-tar-tree
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-grep(1)
NAME NAME
---- ----
git-grep - print lines matching a pattern git-grep - Print lines matching a pattern
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-hash-object(1)
NAME NAME
---- ----
git-hash-object - Computes object ID and optionally creates a blob from a file. git-hash-object - Computes object ID and optionally creates a blob from a file
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-http-push(1)
NAME NAME
---- ----
git-http-push - Push missing objects using HTTP/DAV. git-http-push - Push missing objects using HTTP/DAV
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-lost-found(1)
NAME NAME
---- ----
git-lost-found - Recover lost refs that luckily have not yet been pruned. git-lost-found - Recover lost refs that luckily have not yet been pruned
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-ls-remote(1)
NAME NAME
---- ----
git-ls-remote - Look at references other repository has. git-ls-remote - Look at references other repository has
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-ls-tree(1)
NAME NAME
---- ----
git-ls-tree - Lists the contents of a tree object. git-ls-tree - Lists the contents of a tree object
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-mailinfo(1)
NAME NAME
---- ----
git-mailinfo - Extracts patch from a single e-mail message. git-mailinfo - Extracts patch from a single e-mail message
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-mailsplit(1)
NAME NAME
---- ----
git-mailsplit - Totally braindamaged mbox splitter program. git-mailsplit - Totally braindamaged mbox splitter program
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-mv(1)
NAME NAME
---- ----
git-mv - Script used to move or rename a file, directory or symlink. git-mv - Move or rename a file, directory or symlink
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-name-rev(1)
NAME NAME
---- ----
git-name-rev - Find symbolic names for given revs. git-name-rev - Find symbolic names for given revs
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-pack-objects(1)
NAME NAME
---- ----
git-pack-objects - Create a packed archive of objects. git-pack-objects - Create a packed archive of objects
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-pack-redundant(1)
NAME NAME
---- ----
git-pack-redundant - Program used to find redundant pack files. git-pack-redundant - Program used to find redundant pack files
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-patch-id(1)
NAME NAME
---- ----
git-patch-id - Generate a patch ID. git-patch-id - Generate a patch ID
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-peek-remote(1)
NAME NAME
---- ----
git-peek-remote - Lists the references in a remote repository. git-peek-remote - Lists the references in a remote repository
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-pull(1)
NAME NAME
---- ----
git-pull - Pull and merge from another repository. git-pull - Pull and merge from another repository
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-push(1)
NAME NAME
---- ----
git-push - Update remote refs along with associated objects. git-push - Update remote refs along with associated objects
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-rebase(1)
NAME NAME
---- ----
git-rebase - Rebase local commits to new upstream head. git-rebase - Rebase local commits to new upstream head
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-relink(1)
NAME NAME
---- ----
git-relink - Hardlink common objects in local repositories. git-relink - Hardlink common objects in local repositories
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-repo-config(1)
NAME NAME
---- ----
git-repo-config - Get and set options in .git/config. git-repo-config - Get and set options in .git/config
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-request-pull(1)
NAME NAME
---- ----
git-request-pull - Generates a summary of pending changes. git-request-pull - Generates a summary of pending changes
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-reset(1)
NAME NAME
---- ----
git-reset - Reset current HEAD to the specified state. git-reset - Reset current HEAD to the specified state
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-rev-parse(1)
NAME NAME
---- ----
git-rev-parse - Pick out and massage parameters. git-rev-parse - Pick out and massage parameters
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-revert(1)
NAME NAME
---- ----
git-revert - Revert an existing commit. git-revert - Revert an existing commit
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-rm(1)
NAME NAME
---- ----
git-rm - Remove files from the working tree and from the index. git-rm - Remove files from the working tree and from the index
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-send-pack(1)
NAME NAME
---- ----
git-send-pack - Push missing objects packed. git-send-pack - Push missing objects packed
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-sh-setup(1)
NAME NAME
---- ----
git-sh-setup - Common git shell script setup code. git-sh-setup - Common git shell script setup code
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-shortlog(1)
NAME NAME
---- ----
git-shortlog - Summarize 'git log' output. git-shortlog - Summarize 'git log' output
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-show-branch(1)
NAME NAME
---- ----
git-show-branch - Show branches and their commits. git-show-branch - Show branches and their commits
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-show(1)
NAME NAME
---- ----
git-show - Show one commit with difference it introduces. git-show - Show one commit with difference it introduces
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-status(1)
NAME NAME
---- ----
git-status - Show working tree status. git-status - Show working tree status
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-stripspace(1)
NAME NAME
---- ----
git-stripspace - Filter out empty lines. git-stripspace - Filter out empty lines
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-tag(1)
NAME NAME
---- ----
git-tag - Create a tag object signed with GPG git-tag - Create a tag object signed with GPG
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-unpack-objects(1)
NAME NAME
---- ----
git-unpack-objects - Unpack objects from a packed archive. git-unpack-objects - Unpack objects from a packed archive
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-upload-pack(1)
NAME NAME
---- ----
git-upload-pack - Send missing objects packed. git-upload-pack - Send missing objects packed
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-verify-pack(1)
NAME NAME
---- ----
git-verify-pack - Validate packed git archive files. git-verify-pack - Validate packed git archive files
SYNOPSIS SYNOPSIS

View File

@ -3,7 +3,7 @@ git-verify-tag(1)
NAME NAME
---- ----
git-verify-tag - Check the GPG signature of tag. git-verify-tag - Check the GPG signature of tag
SYNOPSIS SYNOPSIS
-------- --------

View File

@ -3,7 +3,7 @@ git-whatchanged(1)
NAME NAME
---- ----
git-whatchanged - Show logs with difference each commit introduces. git-whatchanged - Show logs with difference each commit introduces
SYNOPSIS SYNOPSIS

View File

@ -20,15 +20,16 @@ brings your stuff to the plumbing).
OPTIONS OPTIONS
------- -------
--version:: --version::
prints the git suite version that the 'git' program came from. Prints the git suite version that the 'git' program came from.
--help:: --help::
prints the synopsis and a list of available commands. Prints the synopsis and a list of the most commonly used
If a git command is named this option will bring up the commands. If a git command is named this option will bring up
man-page for that command. the man-page for that command. If the option '--all' or '-a' is
given then all available commands are printed.
--exec-path:: --exec-path::
path to wherever your core git programs are installed. Path to wherever your core git programs are installed.
This can also be controlled by setting the GIT_EXEC_PATH This can also be controlled by setting the GIT_EXEC_PATH
environment variable. If no path is given 'git' will print environment variable. If no path is given 'git' will print
the current setting and then exit. the current setting and then exit.

View File

@ -452,10 +452,13 @@ all:
strip: $(PROGRAMS) git$X strip: $(PROGRAMS) git$X
$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X $(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
git$X: git.c $(LIB_FILE) git$X: git.c common-cmds.h $(LIB_FILE)
$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \ $(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
$(ALL_CFLAGS) -o $@ $(filter %.c,$^) $(LIB_FILE) $(LIBS) $(ALL_CFLAGS) -o $@ $(filter %.c,$^) $(LIB_FILE) $(LIBS)
common-cmds.h: Documentation/git-*.txt
./generate-cmdlist.sh > $@
$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
rm -f $@ rm -f $@
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
@ -564,7 +567,7 @@ test-date$X: test-date.c date.o ctype.o
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) test-date.c date.o ctype.o $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) test-date.c date.o ctype.o
test-delta$X: test-delta.c diff-delta.o patch-delta.o test-delta$X: test-delta.c diff-delta.o patch-delta.o
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $^ $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $^ -lz
check: check:
for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done
@ -612,7 +615,7 @@ rpm: dist
clean: clean:
rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o $(LIB_FILE) rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o $(LIB_FILE)
rm -f $(ALL_PROGRAMS) git$X rm -f $(ALL_PROGRAMS) git$X
rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h
rm -rf $(GIT_TARNAME) rm -rf $(GIT_TARNAME)
rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
$(MAKE) -C Documentation/ clean $(MAKE) -C Documentation/ clean

View File

@ -651,7 +651,7 @@ static int parse_git_header(char *line, int len, unsigned int size, struct patch
len = linelen(line, size); len = linelen(line, size);
if (!len || line[len-1] != '\n') if (!len || line[len-1] != '\n')
break; break;
for (i = 0; i < sizeof(optable) / sizeof(optable[0]); i++) { for (i = 0; i < ARRAY_SIZE(optable); i++) {
const struct opentry *p = optable + i; const struct opentry *p = optable + i;
int oplen = strlen(p->str); int oplen = strlen(p->str);
if (len < oplen || memcmp(p->str, line, oplen)) if (len < oplen || memcmp(p->str, line, oplen))

View File

@ -30,6 +30,7 @@ my $sha1_short = qr/[a-f\d]{4,40}/;
my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit, my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit,
$_find_copies_harder, $_l, $_version, $_upgrade, $_authors); $_find_copies_harder, $_l, $_version, $_upgrade, $_authors);
my (@_branch_from, %tree_map, %users); my (@_branch_from, %tree_map, %users);
my $_svn_co_url_revs;
my %fc_opts = ( 'no-ignore-externals' => \$_no_ignore_ext, my %fc_opts = ( 'no-ignore-externals' => \$_no_ignore_ext,
'branch|b=s' => \@_branch_from, 'branch|b=s' => \@_branch_from,
@ -77,7 +78,7 @@ usage(0) if $_help;
version() if $_version; version() if $_version;
usage(1) unless defined $cmd; usage(1) unless defined $cmd;
load_authors() if $_authors; load_authors() if $_authors;
svn_check_ignore_externals(); svn_compat_check();
$cmd{$cmd}->[0]->(@ARGV); $cmd{$cmd}->[0]->(@ARGV);
exit 0; exit 0;
@ -154,7 +155,7 @@ sub rebuild {
# if we merged or otherwise started elsewhere, this is # if we merged or otherwise started elsewhere, this is
# how we break out of it # how we break out of it
next if (defined $SVN_UUID && ($uuid ne $SVN_UUID)); next if (defined $SVN_UUID && ($uuid ne $SVN_UUID));
next if (defined $SVN_URL && ($url ne $SVN_URL)); next if (defined $SVN_URL && defined $url && ($url ne $SVN_URL));
print "r$rev = $c\n"; print "r$rev = $c\n";
unless (defined $latest) { unless (defined $latest) {
@ -162,7 +163,8 @@ sub rebuild {
croak "SVN repository location required: $url\n"; croak "SVN repository location required: $url\n";
} }
$SVN_URL ||= $url; $SVN_URL ||= $url;
$SVN_UUID ||= setup_git_svn(); $SVN_UUID ||= $uuid;
setup_git_svn();
$latest = $rev; $latest = $rev;
} }
assert_revision_eq_or_unknown($rev, $c); assert_revision_eq_or_unknown($rev, $c);
@ -171,9 +173,7 @@ sub rebuild {
} }
close $rev_list or croak $?; close $rev_list or croak $?;
if (!chdir $SVN_WC) { if (!chdir $SVN_WC) {
my @svn_co = ('svn','co',"-r$latest"); svn_cmd_checkout($SVN_URL, $latest, $SVN_WC);
push @svn_co, '--ignore-externals' unless $_no_ignore_ext;
sys(@svn_co, $SVN_URL, $SVN_WC);
chdir $SVN_WC or croak $!; chdir $SVN_WC or croak $!;
} }
@ -222,14 +222,14 @@ sub fetch {
my $base = shift @$svn_log or croak "No base revision!\n"; my $base = shift @$svn_log or croak "No base revision!\n";
my $last_commit = undef; my $last_commit = undef;
unless (-d $SVN_WC) { unless (-d $SVN_WC) {
my @svn_co = ('svn','co',"-r$base->{revision}"); svn_cmd_checkout($SVN_URL,$base->{revision},$SVN_WC);
push @svn_co,'--ignore-externals' unless $_no_ignore_ext;
sys(@svn_co, $SVN_URL, $SVN_WC);
chdir $SVN_WC or croak $!; chdir $SVN_WC or croak $!;
read_uuid();
$last_commit = git_commit($base, @parents); $last_commit = git_commit($base, @parents);
assert_svn_wc_clean($base->{revision}, $last_commit); assert_svn_wc_clean($base->{revision}, $last_commit);
} else { } else {
chdir $SVN_WC or croak $!; chdir $SVN_WC or croak $!;
read_uuid();
$last_commit = file_to_s("$REV_DIR/$base->{revision}"); $last_commit = file_to_s("$REV_DIR/$base->{revision}");
} }
my @svn_up = qw(svn up); my @svn_up = qw(svn up);
@ -275,7 +275,9 @@ sub commit {
fetch(); fetch();
chdir $SVN_WC or croak $!; chdir $SVN_WC or croak $!;
my $svn_current_rev = svn_info('.')->{'Last Changed Rev'}; my $info = svn_info('.');
read_uuid($info);
my $svn_current_rev = $info->{'Last Changed Rev'};
foreach my $c (@revs) { foreach my $c (@revs) {
my $mods = svn_checkout_tree($svn_current_rev, $c); my $mods = svn_checkout_tree($svn_current_rev, $c);
if (scalar @$mods == 0) { if (scalar @$mods == 0) {
@ -314,6 +316,14 @@ sub show_ignore {
########################### utility functions ######################### ########################### utility functions #########################
sub read_uuid {
return if $SVN_UUID;
my $info = shift || svn_info('.');
$SVN_UUID = $info->{'Repository UUID'} or
croak "Repository UUID unreadable\n";
s_to_file($SVN_UUID,"$GIT_DIR/$GIT_SVN/info/uuid");
}
sub setup_git_svn { sub setup_git_svn {
defined $SVN_URL or croak "SVN repository location required\n"; defined $SVN_URL or croak "SVN repository location required\n";
unless (-d $GIT_DIR) { unless (-d $GIT_DIR) {
@ -323,14 +333,10 @@ sub setup_git_svn {
mkpath(["$GIT_DIR/$GIT_SVN/info"]); mkpath(["$GIT_DIR/$GIT_SVN/info"]);
mkpath([$REV_DIR]); mkpath([$REV_DIR]);
s_to_file($SVN_URL,"$GIT_DIR/$GIT_SVN/info/url"); s_to_file($SVN_URL,"$GIT_DIR/$GIT_SVN/info/url");
$SVN_UUID = svn_info($SVN_URL)->{'Repository UUID'} or
croak "Repository UUID unreadable\n";
s_to_file($SVN_UUID,"$GIT_DIR/$GIT_SVN/info/uuid");
open my $fd, '>>', "$GIT_DIR/$GIT_SVN/info/exclude" or croak $!; open my $fd, '>>', "$GIT_DIR/$GIT_SVN/info/exclude" or croak $!;
print $fd '.svn',"\n"; print $fd '.svn',"\n";
close $fd or croak $!; close $fd or croak $!;
return $SVN_UUID;
} }
sub assert_svn_wc_clean { sub assert_svn_wc_clean {
@ -860,7 +866,6 @@ sub git_commit {
my ($log_msg, @parents) = @_; my ($log_msg, @parents) = @_;
assert_revision_unknown($log_msg->{revision}); assert_revision_unknown($log_msg->{revision});
my $out_fh = IO::File->new_tmpfile or croak $!; my $out_fh = IO::File->new_tmpfile or croak $!;
$SVN_UUID ||= svn_info('.')->{'Repository UUID'};
map_tree_joins() if (@_branch_from && !%tree_map); map_tree_joins() if (@_branch_from && !%tree_map);
@ -922,7 +927,16 @@ sub git_commit {
} }
my @update_ref = ('git-update-ref',"refs/remotes/$GIT_SVN",$commit); my @update_ref = ('git-update-ref',"refs/remotes/$GIT_SVN",$commit);
if (my $primary_parent = shift @exec_parents) { if (my $primary_parent = shift @exec_parents) {
push @update_ref, $primary_parent; $pid = fork;
defined $pid or croak $!;
if (!$pid) {
close STDERR;
close STDOUT;
exec 'git-rev-parse','--verify',
"refs/remotes/$GIT_SVN^0";
}
waitpid $pid, 0;
push @update_ref, $primary_parent unless $?;
} }
sys(@update_ref); sys(@update_ref);
sys('git-update-ref',"$GIT_SVN/revs/$log_msg->{revision}",$commit); sys('git-update-ref',"$GIT_SVN/revs/$log_msg->{revision}",$commit);
@ -995,13 +1009,37 @@ sub safe_qx {
return wantarray ? @ret : join('',@ret); return wantarray ? @ret : join('',@ret);
} }
sub svn_check_ignore_externals { sub svn_compat_check {
return if $_no_ignore_ext; my @co_help = safe_qx(qw(svn co -h));
unless (grep /ignore-externals/,(safe_qx(qw(svn co -h)))) { unless (grep /ignore-externals/,@co_help) {
print STDERR "W: Installed svn version does not support ", print STDERR "W: Installed svn version does not support ",
"--ignore-externals\n"; "--ignore-externals\n";
$_no_ignore_ext = 1; $_no_ignore_ext = 1;
} }
if (grep /usage: checkout URL\[\@REV\]/,@co_help) {
$_svn_co_url_revs = 1;
}
# I really, really hope nobody hits this...
unless (grep /stop-on-copy/, (safe_qx(qw(svn log -h)))) {
print STDERR <<'';
W: The installed svn version does not support the --stop-on-copy flag in
the log command.
Lets hope the directory you're tracking is not a branch or tag
and was never moved within the repository...
$_no_stop_copy = 1;
}
}
# *sigh*, new versions of svn won't honor -r<rev> without URL@<rev>,
# (and they won't honor URL@<rev> without -r<rev>, too!)
sub svn_cmd_checkout {
my ($url, $rev, $dir) = @_;
my @cmd = ('svn','co', "-r$rev");
push @cmd, '--ignore-externals' unless $_no_ignore_ext;
$url .= "\@$rev" if $_svn_co_url_revs;
sys(@cmd, $url, $dir);
} }
sub check_upgrade_needed { sub check_upgrade_needed {

View File

@ -162,21 +162,8 @@ COMPATIBILITY OPTIONS
Otherwise, do not enable this flag unless you know what you're Otherwise, do not enable this flag unless you know what you're
doing. doing.
--no-stop-on-copy:: Basic Examples
Only used with the 'fetch' command. ~~~~~~~~~~~~~~
By default, git-svn passes --stop-on-copy to avoid dealing with
the copied/renamed branch directory problem entirely. A
copied/renamed branch is the result of a <SVN_URL> being created
in the past from a different source. These are problematic to
deal with even when working purely with svn if you work inside
subdirectories.
Do not use this flag unless you know exactly what you're getting
yourself into. You have been warned.
Examples
~~~~~~~~
Tracking and contributing to an Subversion managed-project: Tracking and contributing to an Subversion managed-project:
@ -234,6 +221,34 @@ This allows you to tie unfetched SVN revision 375 to your current HEAD::
git-svn fetch 375=$(git-rev-parse HEAD) git-svn fetch 375=$(git-rev-parse HEAD)
Advanced Example: Tracking a Reorganized Repository
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you're tracking a directory that has moved, or otherwise been
branched or tagged off of another directory in the repository and you
care about the full history of the project, then you can read this
section.
This is how Yann Dirson tracked the trunk of the ufoai directory when
the /trunk directory of his repository was moved to /ufoai/trunk and
he needed to continue tracking /ufoai/trunk where /trunk left off.
# This log message shows when the repository was reorganized::
r166 | ydirson | 2006-03-02 01:36:55 +0100 (Thu, 02 Mar 2006) | 1 line
Changed paths:
D /trunk
A /ufoai/trunk (from /trunk:165)
# First we start tracking the old revisions::
GIT_SVN_ID=git-oldsvn git-svn init \
https://svn.sourceforge.net/svnroot/ufoai/trunk
GIT_SVN_ID=git-oldsvn git-svn fetch -r1:165
# And now, we continue tracking the new revisions::
GIT_SVN_ID=git-newsvn git-svn init \
https://svn.sourceforge.net/svnroot/ufoai/ufoai/trunk
GIT_SVN_ID=git-newsvn git-svn fetch \
166=`git-rev-parse refs/remotes/git-oldsvn`
BUGS BUGS
---- ----
If somebody commits a conflicting changeset to SVN at a bad moment If somebody commits a conflicting changeset to SVN at a bad moment

4
date.c
View File

@ -123,8 +123,6 @@ static const struct {
{ "IDLE", +12, 0, }, /* International Date Line East */ { "IDLE", +12, 0, }, /* International Date Line East */
}; };
#define NR_TZ (sizeof(timezone_names) / sizeof(timezone_names[0]))
static int match_string(const char *date, const char *str) static int match_string(const char *date, const char *str)
{ {
int i = 0; int i = 0;
@ -173,7 +171,7 @@ static int match_alpha(const char *date, struct tm *tm, int *offset)
} }
} }
for (i = 0; i < NR_TZ; i++) { for (i = 0; i < ARRAY_SIZE(timezone_names); i++) {
int match = match_string(date, timezone_names[i].name); int match = match_string(date, timezone_names[i].name);
if (match >= 3) { if (match >= 3) {
int off = timezone_names[i].offset; int off = timezone_names[i].offset;

View File

@ -40,17 +40,18 @@ struct index {
static struct index ** delta_index(const unsigned char *buf, static struct index ** delta_index(const unsigned char *buf,
unsigned long bufsize, unsigned long bufsize,
unsigned long trg_bufsize,
unsigned int *hash_shift) unsigned int *hash_shift)
{ {
unsigned int hsize, hshift, entries, blksize, i; unsigned int i, hsize, hshift, hlimit, entries, *hash_count;
const unsigned char *data; const unsigned char *data;
struct index *entry, **hash; struct index *entry, **hash;
void *mem; void *mem;
/* determine index hash size */ /* determine index hash size */
entries = (bufsize + BLK_SIZE - 1) / BLK_SIZE; entries = bufsize / BLK_SIZE;
hsize = entries / 4; hsize = entries / 4;
for (i = 4; (1 << i) < hsize && i < 16; i++); for (i = 4; (1 << i) < hsize && i < 31; i++);
hsize = 1 << i; hsize = 1 << i;
hshift = 32 - i; hshift = 32 - i;
*hash_shift = hshift; *hash_shift = hshift;
@ -63,20 +64,62 @@ static struct index ** delta_index(const unsigned char *buf,
entry = mem + hsize * sizeof(*hash); entry = mem + hsize * sizeof(*hash);
memset(hash, 0, hsize * sizeof(*hash)); memset(hash, 0, hsize * sizeof(*hash));
/* then populate it */ /* allocate an array to count hash entries */
hash_count = calloc(hsize, sizeof(*hash_count));
if (!hash_count) {
free(hash);
return NULL;
}
/* then populate the index */
data = buf + entries * BLK_SIZE - BLK_SIZE; data = buf + entries * BLK_SIZE - BLK_SIZE;
blksize = bufsize - (data - buf);
while (data >= buf) { while (data >= buf) {
unsigned int val = adler32(0, data, blksize); unsigned int val = adler32(0, data, BLK_SIZE);
i = HASH(val, hshift); i = HASH(val, hshift);
entry->ptr = data; entry->ptr = data;
entry->val = val; entry->val = val;
entry->next = hash[i]; entry->next = hash[i];
hash[i] = entry++; hash[i] = entry++;
blksize = BLK_SIZE; hash_count[i]++;
data -= BLK_SIZE; data -= BLK_SIZE;
} }
/*
* Determine a limit on the number of entries in the same hash
* bucket. This guard us against patological data sets causing
* really bad hash distribution with most entries in the same hash
* bucket that would bring us to O(m*n) computing costs (m and n
* corresponding to reference and target buffer sizes).
*
* The more the target buffer is large, the more it is important to
* have small entry lists for each hash buckets. With such a limit
* the cost is bounded to something more like O(m+n).
*/
hlimit = (1 << 26) / trg_bufsize;
if (hlimit < 4*BLK_SIZE)
hlimit = 4*BLK_SIZE;
/*
* Now make sure none of the hash buckets has more entries than
* we're willing to test. Otherwise we cull the entry list
* uniformly to still preserve a good repartition across
* the reference buffer.
*/
for (i = 0; i < hsize; i++) {
if (hash_count[i] < hlimit)
continue;
entry = hash[i];
do {
struct index *keep = entry;
int skip = hash_count[i] / hlimit / 2;
do {
entry = entry->next;
} while(--skip && entry);
keep->next = entry;
} while(entry);
}
free(hash_count);
return hash; return hash;
} }
@ -100,7 +143,7 @@ void *diff_delta(void *from_buf, unsigned long from_size,
if (!from_size || !to_size) if (!from_size || !to_size)
return NULL; return NULL;
hash = delta_index(from_buf, from_size, &hash_shift); hash = delta_index(from_buf, from_size, to_size, &hash_shift);
if (!hash) if (!hash)
return NULL; return NULL;
@ -141,29 +184,27 @@ void *diff_delta(void *from_buf, unsigned long from_size,
while (data < top) { while (data < top) {
unsigned int moff = 0, msize = 0; unsigned int moff = 0, msize = 0;
unsigned int blksize = MIN(top - data, BLK_SIZE); if (data + BLK_SIZE <= top) {
unsigned int val = adler32(0, data, blksize); unsigned int val = adler32(0, data, BLK_SIZE);
i = HASH(val, hash_shift); i = HASH(val, hash_shift);
for (entry = hash[i]; entry; entry = entry->next) { for (entry = hash[i]; entry; entry = entry->next) {
const unsigned char *ref = entry->ptr; const unsigned char *ref = entry->ptr;
const unsigned char *src = data; const unsigned char *src = data;
unsigned int ref_size = ref_top - ref; unsigned int ref_size = ref_top - ref;
if (entry->val != val) if (entry->val != val)
continue; continue;
if (ref_size > top - src) if (ref_size > top - src)
ref_size = top - src; ref_size = top - src;
while (ref_size && *src++ == *ref) { if (ref_size > 0x10000)
ref++; ref_size = 0x10000;
ref_size--; if (ref_size <= msize)
}
ref_size = ref - entry->ptr;
if (ref_size > msize) {
/* this is our best match so far */
moff = entry->ptr - ref_data;
msize = ref_size;
if (msize >= 0x10000) {
msize = 0x10000;
break; break;
while (ref_size-- && *src++ == *ref)
ref++;
if (msize < ref - entry->ptr) {
/* this is our best match so far */
msize = ref - entry->ptr;
moff = entry->ptr - ref_data;
} }
} }
} }

View File

@ -37,7 +37,7 @@ int execv_git_cmd(const char **argv)
getenv("GIT_EXEC_PATH"), getenv("GIT_EXEC_PATH"),
builtin_exec_path }; builtin_exec_path };
for (i = 0; i < sizeof(paths)/sizeof(paths[0]); ++i) { for (i = 0; i < ARRAY_SIZE(paths); ++i) {
const char *exec_dir = paths[i]; const char *exec_dir = paths[i];
const char *tmp; const char *tmp;

View File

@ -14,10 +14,9 @@
static int show_root = 0; static int show_root = 0;
static int show_tags = 0; static int show_tags = 0;
static int show_unreachable = 0; static int show_unreachable = 0;
static int standalone = 0;
static int check_full = 0; static int check_full = 0;
static int check_strict = 0; static int check_strict = 0;
static int keep_cache_objects = 0; static int keep_cache_objects = 0;
static unsigned char head_sha1[20]; static unsigned char head_sha1[20];
#ifdef NO_D_INO_IN_DIRENT #ifdef NO_D_INO_IN_DIRENT
@ -68,7 +67,7 @@ static void check_connectivity(void)
continue; continue;
if (!obj->parsed) { if (!obj->parsed) {
if (!standalone && has_sha1_file(obj->sha1)) if (has_sha1_file(obj->sha1))
; /* it is in pack */ ; /* it is in pack */
else else
printf("missing %s %s\n", printf("missing %s %s\n",
@ -82,7 +81,7 @@ static void check_connectivity(void)
for (j = 0; j < refs->count; j++) { for (j = 0; j < refs->count; j++) {
struct object *ref = refs->ref[j]; struct object *ref = refs->ref[j];
if (ref->parsed || if (ref->parsed ||
(!standalone && has_sha1_file(ref->sha1))) (has_sha1_file(ref->sha1)))
continue; continue;
printf("broken link from %7s %s\n", printf("broken link from %7s %s\n",
obj->type, sha1_to_hex(obj->sha1)); obj->type, sha1_to_hex(obj->sha1));
@ -390,7 +389,7 @@ static int fsck_handle_ref(const char *refname, const unsigned char *sha1)
obj = lookup_object(sha1); obj = lookup_object(sha1);
if (!obj) { if (!obj) {
if (!standalone && has_sha1_file(sha1)) { if (has_sha1_file(sha1)) {
default_refs++; default_refs++;
return 0; /* it is in a pack */ return 0; /* it is in a pack */
} }
@ -464,10 +463,6 @@ int main(int argc, char **argv)
keep_cache_objects = 1; keep_cache_objects = 1;
continue; continue;
} }
if (!strcmp(arg, "--standalone")) {
standalone = 1;
continue;
}
if (!strcmp(arg, "--full")) { if (!strcmp(arg, "--full")) {
check_full = 1; check_full = 1;
continue; continue;
@ -477,14 +472,9 @@ int main(int argc, char **argv)
continue; continue;
} }
if (*arg == '-') if (*arg == '-')
usage("git-fsck-objects [--tags] [--root] [[--unreachable] [--cache] [--standalone | --full] [--strict] <head-sha1>*]"); usage("git-fsck-objects [--tags] [--root] [[--unreachable] [--cache] [--full] [--strict] <head-sha1>*]");
} }
if (standalone && check_full)
die("Only one of --standalone or --full can be used.");
if (standalone)
putenv("GIT_ALTERNATE_OBJECT_DIRECTORIES=");
fsck_head_link(); fsck_head_link();
fsck_object_dir(get_object_directory()); fsck_object_dir(get_object_directory());
if (check_full) { if (check_full) {

48
generate-cmdlist.sh Executable file
View File

@ -0,0 +1,48 @@
#!/bin/sh
echo "/* Automatically generated by $0 */
struct cmdname_help
{
char name[16];
char help[64];
};
struct cmdname_help common_cmds[] = {"
sort <<\EOF |
add
apply
bisect
branch
checkout
cherry-pick
clone
commit
diff
fetch
grep
init-db
log
merge
mv
prune
pull
push
rebase
reset
revert
rm
show
show-branch
status
tag
verify-tag
whatchanged
EOF
while read cmd
do
sed -n "/NAME/,/git-$cmd/H;
\$ {x; s/.*git-$cmd - \\(.*\\)/ {\"$cmd\", \"\1\"},/; p}" \
"Documentation/git-$cmd.txt"
done
echo "};"

View File

@ -9,6 +9,8 @@
#endif #endif
#endif #endif
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h> #include <sys/stat.h>

View File

@ -47,7 +47,7 @@ sub current_branch {
sub shortlog { sub shortlog {
my ($tip) = @_; my ($tip) = @_;
my @result; my @result;
foreach ( qx{git-log --topo-order --pretty=oneline $tip ^HEAD} ) { foreach ( qx{git-log --no-merges --topo-order --pretty=oneline $tip ^HEAD} ) {
s/^[0-9a-f]{40}\s+//; s/^[0-9a-f]{40}\s+//;
push @result, $_; push @result, $_;
} }

49
git.c
View File

@ -11,6 +11,7 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include "git-compat-util.h" #include "git-compat-util.h"
#include "exec_cmd.h" #include "exec_cmd.h"
#include "common-cmds.h"
#include "cache.h" #include "cache.h"
#include "commit.h" #include "commit.h"
@ -171,11 +172,29 @@ static void list_commands(const char *exec_path, const char *pattern)
putchar('\n'); putchar('\n');
} }
static void list_common_cmds_help()
{
int i, longest = 0;
for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
if (longest < strlen(common_cmds[i].name))
longest = strlen(common_cmds[i].name);
}
puts("The most commonly used git commands are:");
for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
printf(" %s", common_cmds[i].name);
mput_char(' ', longest - strlen(common_cmds[i].name) + 4);
puts(common_cmds[i].help);
}
puts("(use 'git help -a' to get a list of all installed git commands)");
}
#ifdef __GNUC__ #ifdef __GNUC__
static void cmd_usage(const char *exec_path, const char *fmt, ...) static void cmd_usage(int show_all, const char *exec_path, const char *fmt, ...)
__attribute__((__format__(__printf__, 2, 3), __noreturn__)); __attribute__((__format__(__printf__, 3, 4), __noreturn__));
#endif #endif
static void cmd_usage(const char *exec_path, const char *fmt, ...) static void cmd_usage(int show_all, const char *exec_path, const char *fmt, ...)
{ {
if (fmt) { if (fmt) {
va_list ap; va_list ap;
@ -189,10 +208,13 @@ static void cmd_usage(const char *exec_path, const char *fmt, ...)
else else
puts(git_usage); puts(git_usage);
putchar('\n'); if (exec_path) {
putchar('\n');
if(exec_path) if (show_all)
list_commands(exec_path, "git-*"); list_commands(exec_path, "git-*");
else
list_common_cmds_help();
}
exit(1); exit(1);
} }
@ -244,8 +266,11 @@ static int cmd_help(int argc, const char **argv, char **envp)
{ {
const char *help_cmd = argv[1]; const char *help_cmd = argv[1];
if (!help_cmd) if (!help_cmd)
cmd_usage(git_exec_path(), NULL); cmd_usage(0, git_exec_path(), NULL);
show_man_page(help_cmd); else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a"))
cmd_usage(1, git_exec_path(), NULL);
else
show_man_page(help_cmd);
return 0; return 0;
} }
@ -323,8 +348,6 @@ static int cmd_log(int argc, const char **argv, char **envp)
return 0; return 0;
} }
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
static void handle_internal_command(int argc, const char **argv, char **envp) static void handle_internal_command(int argc, const char **argv, char **envp)
{ {
const char *cmd = argv[0]; const char *cmd = argv[0];
@ -420,7 +443,7 @@ int main(int argc, const char **argv, char **envp)
puts(git_exec_path()); puts(git_exec_path());
exit(0); exit(0);
} }
cmd_usage(NULL, NULL); cmd_usage(0, NULL, NULL);
} }
argv[0] = cmd; argv[0] = cmd;
@ -443,7 +466,7 @@ int main(int argc, const char **argv, char **envp)
execv_git_cmd(argv); execv_git_cmd(argv);
if (errno == ENOENT) if (errno == ENOENT)
cmd_usage(exec_path, "'%s' is not a git-command", cmd); cmd_usage(0, exec_path, "'%s' is not a git-command", cmd);
fprintf(stderr, "Failed to run command '%s': %s\n", fprintf(stderr, "Failed to run command '%s': %s\n",
git_command, strerror(errno)); git_command, strerror(errno));

6
refs.c
View File

@ -152,12 +152,12 @@ static int do_for_each_ref(const char *base, int (*fn)(const char *path, const u
continue; continue;
} }
if (read_ref(git_path("%s", path), sha1) < 0) { if (read_ref(git_path("%s", path), sha1) < 0) {
fprintf(stderr, "%s points nowhere!", path); error("%s points nowhere!", path);
continue; continue;
} }
if (!has_sha1_file(sha1)) { if (!has_sha1_file(sha1)) {
fprintf(stderr, "%s does not point to a valid " error("%s does not point to a valid "
"commit object!", path); "commit object!", path);
continue; continue;
} }
retval = fn(path, sha1); retval = fn(path, sha1);

View File

@ -82,18 +82,20 @@ void mark_parents_uninteresting(struct commit *commit)
while (parents) { while (parents) {
struct commit *commit = parents->item; struct commit *commit = parents->item;
commit->object.flags |= UNINTERESTING; if (!(commit->object.flags & UNINTERESTING)) {
commit->object.flags |= UNINTERESTING;
/* /*
* Normally we haven't parsed the parent * Normally we haven't parsed the parent
* yet, so we won't have a parent of a parent * yet, so we won't have a parent of a parent
* here. However, it may turn out that we've * here. However, it may turn out that we've
* reached this commit some other way (where it * reached this commit some other way (where it
* wasn't uninteresting), in which case we need * wasn't uninteresting), in which case we need
* to mark its parents recursively too.. * to mark its parents recursively too..
*/ */
if (commit->parents) if (commit->parents)
mark_parents_uninteresting(commit); mark_parents_uninteresting(commit);
}
/* /*
* A missing commit is ok iff its parent is marked * A missing commit is ok iff its parent is marked