git-core-*/?*
test-date
test-delta
+common-cmds.h
*.tar.gz
*.dsc
*.deb
NAME
----
-git-add - Add files to the index file.
+git-add - Add files to the index file
SYNOPSIS
--------
NAME
----
-git-applypatch - Apply one patch extracted from an e-mail.
+git-applypatch - Apply one patch extracted from an e-mail
SYNOPSIS
NAME
----
-git-branch - Create a new branch, or remove an old one.
+git-branch - Create a new branch, or remove an old one
SYNOPSIS
--------
NAME
----
-git-check-ref-format - Make sure ref name is well formed.
+git-check-ref-format - Make sure ref name is well formed
SYNOPSIS
--------
NAME
----
-git-checkout - Checkout and switch to a branch.
+git-checkout - Checkout and switch to a branch
SYNOPSIS
--------
NAME
----
-git-cherry-pick - Apply the change introduced by an existing commit.
+git-cherry-pick - Apply the change introduced by an existing commit
SYNOPSIS
--------
NAME
----
-git-cherry - Find commits not merged upstream.
+git-cherry - Find commits not merged upstream
SYNOPSIS
--------
NAME
----
-git-clone-pack - Clones a repository by receiving packed objects.
+git-clone-pack - Clones a repository by receiving packed objects
SYNOPSIS
NAME
----
-git-clone - Clones a repository.
+git-clone - Clones a repository
SYNOPSIS
NAME
----
-git-count-objects - Reports on unpacked objects.
+git-count-objects - Reports on unpacked objects
SYNOPSIS
--------
NAME
----
-git-daemon - A really simple server for git repositories.
+git-daemon - A really simple server for git repositories
SYNOPSIS
--------
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
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
NAME
----
-git-diff - Show changes between commits, commit and working tree, etc.
+git-diff - Show changes between commits, commit and working tree, etc
SYNOPSIS
NAME
----
-git-fetch-pack - Receive missing objects from another repository.
+git-fetch-pack - Receive missing objects from another repository
SYNOPSIS
NAME
----
-git-fetch - Download objects and a head from another repository.
+git-fetch - Download objects and a head from another repository
SYNOPSIS
NAME
----
-git-format-patch - Prepare patches for e-mail submission.
+git-format-patch - Prepare patches for e-mail submission
SYNOPSIS
--------
[verse]
'git-fsck-objects' [--tags] [--root] [--unreachable] [--cache]
- [--standalone | --full] [--strict] [<object>*]
+ [--full] [--strict] [<object>*]
DESCRIPTION
-----------
Consider any object recorded in the index also as a head node for
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::
Check not just objects in GIT_OBJECT_DIRECTORY
($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 corresponding pack subdirectories in alternate
- object pools; cannot be used with --standalone.
+ object pools.
--strict::
Enable more strict checking, namely to catch a file mode
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
NAME
----
-git-grep - print lines matching a pattern
+git-grep - Print lines matching a pattern
SYNOPSIS
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
NAME
----
-git-http-push - Push missing objects using HTTP/DAV.
+git-http-push - Push missing objects using HTTP/DAV
SYNOPSIS
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
--------
NAME
----
-git-ls-remote - Look at references other repository has.
+git-ls-remote - Look at references other repository has
SYNOPSIS
NAME
----
-git-ls-tree - Lists the contents of a tree object.
+git-ls-tree - Lists the contents of a tree object
SYNOPSIS
NAME
----
-git-mailinfo - Extracts patch from a single e-mail message.
+git-mailinfo - Extracts patch from a single e-mail message
SYNOPSIS
NAME
----
-git-mailsplit - Totally braindamaged mbox splitter program.
+git-mailsplit - Totally braindamaged mbox splitter program
SYNOPSIS
--------
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
NAME
----
-git-name-rev - Find symbolic names for given revs.
+git-name-rev - Find symbolic names for given revs
SYNOPSIS
NAME
----
-git-pack-objects - Create a packed archive of objects.
+git-pack-objects - Create a packed archive of objects
SYNOPSIS
NAME
----
-git-pack-redundant - Program used to find redundant pack files.
+git-pack-redundant - Program used to find redundant pack files
SYNOPSIS
NAME
----
-git-patch-id - Generate a patch ID.
+git-patch-id - Generate a patch ID
SYNOPSIS
--------
NAME
----
-git-peek-remote - Lists the references in a remote repository.
+git-peek-remote - Lists the references in a remote repository
SYNOPSIS
NAME
----
-git-pull - Pull and merge from another repository.
+git-pull - Pull and merge from another repository
SYNOPSIS
NAME
----
-git-push - Update remote refs along with associated objects.
+git-push - Update remote refs along with associated objects
SYNOPSIS
NAME
----
-git-rebase - Rebase local commits to new upstream head.
+git-rebase - Rebase local commits to new upstream head
SYNOPSIS
--------
NAME
----
-git-relink - Hardlink common objects in local repositories.
+git-relink - Hardlink common objects in local repositories
SYNOPSIS
--------
NAME
----
-git-repo-config - Get and set options in .git/config.
+git-repo-config - Get and set options in .git/config
SYNOPSIS
NAME
----
-git-request-pull - Generates a summary of pending changes.
+git-request-pull - Generates a summary of pending changes
SYNOPSIS
--------
NAME
----
-git-reset - Reset current HEAD to the specified state.
+git-reset - Reset current HEAD to the specified state
SYNOPSIS
--------
NAME
----
-git-rev-parse - Pick out and massage parameters.
+git-rev-parse - Pick out and massage parameters
SYNOPSIS
NAME
----
-git-revert - Revert an existing commit.
+git-revert - Revert an existing commit
SYNOPSIS
--------
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
--------
NAME
----
-git-send-pack - Push missing objects packed.
+git-send-pack - Push missing objects packed
SYNOPSIS
NAME
----
-git-sh-setup - Common git shell script setup code.
+git-sh-setup - Common git shell script setup code
SYNOPSIS
--------
NAME
----
-git-shortlog - Summarize 'git log' output.
+git-shortlog - Summarize 'git log' output
SYNOPSIS
NAME
----
-git-show-branch - Show branches and their commits.
+git-show-branch - Show branches and their commits
SYNOPSIS
--------
NAME
----
-git-show - Show one commit with difference it introduces.
+git-show - Show one commit with difference it introduces
SYNOPSIS
NAME
----
-git-status - Show working tree status.
+git-status - Show working tree status
SYNOPSIS
NAME
----
-git-stripspace - Filter out empty lines.
+git-stripspace - Filter out empty lines
SYNOPSIS
NAME
----
-git-tag - Create a tag object signed with GPG
+git-tag - Create a tag object signed with GPG
SYNOPSIS
NAME
----
-git-unpack-objects - Unpack objects from a packed archive.
+git-unpack-objects - Unpack objects from a packed archive
SYNOPSIS
NAME
----
-git-upload-pack - Send missing objects packed.
+git-upload-pack - Send missing objects packed
SYNOPSIS
NAME
----
-git-verify-pack - Validate packed git archive files.
+git-verify-pack - Validate packed git archive files
SYNOPSIS
NAME
----
-git-verify-tag - Check the GPG signature of tag.
+git-verify-tag - Check the GPG signature of tag
SYNOPSIS
--------
NAME
----
-git-whatchanged - Show logs with difference each commit introduces.
+git-whatchanged - Show logs with difference each commit introduces
SYNOPSIS
OPTIONS
-------
--version::
- prints the git suite version that the 'git' program came from.
+ Prints the git suite version that the 'git' program came from.
--help::
- prints the synopsis and a list of available commands.
- If a git command is named this option will bring up the
- man-page for that command.
+ Prints the synopsis and a list of the most commonly used
+ commands. If a git command is named this option will bring up
+ the man-page for that command. If the option '--all' or '-a' is
+ given then all available commands are printed.
--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
environment variable. If no path is given 'git' will print
the current setting and then exit.
strip: $(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)"' \
$(ALL_CFLAGS) -o $@ $(filter %.c,$^) $(LIB_FILE) $(LIBS)
+common-cmds.h: Documentation/git-*.txt
+ ./generate-cmdlist.sh > $@
+
$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
rm -f $@
sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
$(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
- $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $^
+ $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $^ -lz
check:
for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done
clean:
rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o $(LIB_FILE)
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 -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
$(MAKE) -C Documentation/ clean
len = linelen(line, size);
if (!len || line[len-1] != '\n')
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;
int oplen = strlen(p->str);
if (len < oplen || memcmp(p->str, line, oplen))
my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit,
$_find_copies_harder, $_l, $_version, $_upgrade, $_authors);
my (@_branch_from, %tree_map, %users);
+my $_svn_co_url_revs;
my %fc_opts = ( 'no-ignore-externals' => \$_no_ignore_ext,
'branch|b=s' => \@_branch_from,
version() if $_version;
usage(1) unless defined $cmd;
load_authors() if $_authors;
-svn_check_ignore_externals();
+svn_compat_check();
$cmd{$cmd}->[0]->(@ARGV);
exit 0;
# if we merged or otherwise started elsewhere, this is
# how we break out of it
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";
unless (defined $latest) {
croak "SVN repository location required: $url\n";
}
$SVN_URL ||= $url;
- $SVN_UUID ||= setup_git_svn();
+ $SVN_UUID ||= $uuid;
+ setup_git_svn();
$latest = $rev;
}
assert_revision_eq_or_unknown($rev, $c);
}
close $rev_list or croak $?;
if (!chdir $SVN_WC) {
- my @svn_co = ('svn','co',"-r$latest");
- push @svn_co, '--ignore-externals' unless $_no_ignore_ext;
- sys(@svn_co, $SVN_URL, $SVN_WC);
+ svn_cmd_checkout($SVN_URL, $latest, $SVN_WC);
chdir $SVN_WC or croak $!;
}
my $base = shift @$svn_log or croak "No base revision!\n";
my $last_commit = undef;
unless (-d $SVN_WC) {
- my @svn_co = ('svn','co',"-r$base->{revision}");
- push @svn_co,'--ignore-externals' unless $_no_ignore_ext;
- sys(@svn_co, $SVN_URL, $SVN_WC);
+ svn_cmd_checkout($SVN_URL,$base->{revision},$SVN_WC);
chdir $SVN_WC or croak $!;
+ read_uuid();
$last_commit = git_commit($base, @parents);
assert_svn_wc_clean($base->{revision}, $last_commit);
} else {
chdir $SVN_WC or croak $!;
+ read_uuid();
$last_commit = file_to_s("$REV_DIR/$base->{revision}");
}
my @svn_up = qw(svn up);
fetch();
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) {
my $mods = svn_checkout_tree($svn_current_rev, $c);
if (scalar @$mods == 0) {
########################### 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 {
defined $SVN_URL or croak "SVN repository location required\n";
unless (-d $GIT_DIR) {
mkpath(["$GIT_DIR/$GIT_SVN/info"]);
mkpath([$REV_DIR]);
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 $!;
print $fd '.svn',"\n";
close $fd or croak $!;
- return $SVN_UUID;
}
sub assert_svn_wc_clean {
my ($log_msg, @parents) = @_;
assert_revision_unknown($log_msg->{revision});
my $out_fh = IO::File->new_tmpfile or croak $!;
- $SVN_UUID ||= svn_info('.')->{'Repository UUID'};
map_tree_joins() if (@_branch_from && !%tree_map);
}
my @update_ref = ('git-update-ref',"refs/remotes/$GIT_SVN",$commit);
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('git-update-ref',"$GIT_SVN/revs/$log_msg->{revision}",$commit);
return wantarray ? @ret : join('',@ret);
}
-sub svn_check_ignore_externals {
- return if $_no_ignore_ext;
- unless (grep /ignore-externals/,(safe_qx(qw(svn co -h)))) {
+sub svn_compat_check {
+ my @co_help = safe_qx(qw(svn co -h));
+ unless (grep /ignore-externals/,@co_help) {
print STDERR "W: Installed svn version does not support ",
"--ignore-externals\n";
$_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 {
Otherwise, do not enable this flag unless you know what you're
doing.
---no-stop-on-copy::
- 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
-~~~~~~~~
+Basic Examples
+~~~~~~~~~~~~~~
Tracking and contributing to an Subversion managed-project:
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
----
If somebody commits a conflicting changeset to SVN at a bad moment
{ "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)
{
int i = 0;
}
}
- 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);
if (match >= 3) {
int off = timezone_names[i].offset;
static struct index ** delta_index(const unsigned char *buf,
unsigned long bufsize,
+ unsigned long trg_bufsize,
unsigned int *hash_shift)
{
- unsigned int hsize, hshift, entries, blksize, i;
+ unsigned int i, hsize, hshift, hlimit, entries, *hash_count;
const unsigned char *data;
struct index *entry, **hash;
void *mem;
/* determine index hash size */
- entries = (bufsize + BLK_SIZE - 1) / BLK_SIZE;
+ entries = bufsize / BLK_SIZE;
hsize = entries / 4;
- for (i = 4; (1 << i) < hsize && i < 16; i++);
+ for (i = 4; (1 << i) < hsize && i < 31; i++);
hsize = 1 << i;
hshift = 32 - i;
*hash_shift = hshift;
entry = mem + 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;
- blksize = bufsize - (data - buf);
while (data >= buf) {
- unsigned int val = adler32(0, data, blksize);
+ unsigned int val = adler32(0, data, BLK_SIZE);
i = HASH(val, hshift);
entry->ptr = data;
entry->val = val;
entry->next = hash[i];
hash[i] = entry++;
- blksize = BLK_SIZE;
+ hash_count[i]++;
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;
}
if (!from_size || !to_size)
return NULL;
- hash = delta_index(from_buf, from_size, &hash_shift);
+ hash = delta_index(from_buf, from_size, to_size, &hash_shift);
if (!hash)
return NULL;
while (data < top) {
unsigned int moff = 0, msize = 0;
- unsigned int blksize = MIN(top - data, BLK_SIZE);
- unsigned int val = adler32(0, data, blksize);
- i = HASH(val, hash_shift);
- for (entry = hash[i]; entry; entry = entry->next) {
- const unsigned char *ref = entry->ptr;
- const unsigned char *src = data;
- unsigned int ref_size = ref_top - ref;
- if (entry->val != val)
- continue;
- if (ref_size > top - src)
- ref_size = top - src;
- while (ref_size && *src++ == *ref) {
- ref++;
- ref_size--;
- }
- 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;
+ if (data + BLK_SIZE <= top) {
+ unsigned int val = adler32(0, data, BLK_SIZE);
+ i = HASH(val, hash_shift);
+ for (entry = hash[i]; entry; entry = entry->next) {
+ const unsigned char *ref = entry->ptr;
+ const unsigned char *src = data;
+ unsigned int ref_size = ref_top - ref;
+ if (entry->val != val)
+ continue;
+ if (ref_size > top - src)
+ ref_size = top - src;
+ if (ref_size > 0x10000)
+ ref_size = 0x10000;
+ if (ref_size <= msize)
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;
}
}
}
getenv("GIT_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 *tmp;
static int show_root = 0;
static int show_tags = 0;
static int show_unreachable = 0;
-static int standalone = 0;
static int check_full = 0;
static int check_strict = 0;
-static int keep_cache_objects = 0;
+static int keep_cache_objects = 0;
static unsigned char head_sha1[20];
#ifdef NO_D_INO_IN_DIRENT
continue;
if (!obj->parsed) {
- if (!standalone && has_sha1_file(obj->sha1))
+ if (has_sha1_file(obj->sha1))
; /* it is in pack */
else
printf("missing %s %s\n",
for (j = 0; j < refs->count; j++) {
struct object *ref = refs->ref[j];
if (ref->parsed ||
- (!standalone && has_sha1_file(ref->sha1)))
+ (has_sha1_file(ref->sha1)))
continue;
printf("broken link from %7s %s\n",
obj->type, sha1_to_hex(obj->sha1));
obj = lookup_object(sha1);
if (!obj) {
- if (!standalone && has_sha1_file(sha1)) {
+ if (has_sha1_file(sha1)) {
default_refs++;
return 0; /* it is in a pack */
}
keep_cache_objects = 1;
continue;
}
- if (!strcmp(arg, "--standalone")) {
- standalone = 1;
- continue;
- }
if (!strcmp(arg, "--full")) {
check_full = 1;
continue;
continue;
}
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_object_dir(get_object_directory());
if (check_full) {
--- /dev/null
+#!/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 "};"
#endif
#endif
+#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
+
#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
sub shortlog {
my ($tip) = @_;
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+//;
push @result, $_;
}
#include <sys/ioctl.h>
#include "git-compat-util.h"
#include "exec_cmd.h"
+#include "common-cmds.h"
#include "cache.h"
#include "commit.h"
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__
-static void cmd_usage(const char *exec_path, const char *fmt, ...)
- __attribute__((__format__(__printf__, 2, 3), __noreturn__));
+static void cmd_usage(int show_all, const char *exec_path, const char *fmt, ...)
+ __attribute__((__format__(__printf__, 3, 4), __noreturn__));
#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) {
va_list ap;
else
puts(git_usage);
- putchar('\n');
-
- if(exec_path)
- list_commands(exec_path, "git-*");
+ if (exec_path) {
+ putchar('\n');
+ if (show_all)
+ list_commands(exec_path, "git-*");
+ else
+ list_common_cmds_help();
+ }
exit(1);
}
{
const char *help_cmd = argv[1];
if (!help_cmd)
- cmd_usage(git_exec_path(), NULL);
- show_man_page(help_cmd);
+ cmd_usage(0, git_exec_path(), NULL);
+ 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;
}
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
-
static void handle_internal_command(int argc, const char **argv, char **envp)
{
const char *cmd = argv[0];
puts(git_exec_path());
exit(0);
}
- cmd_usage(NULL, NULL);
+ cmd_usage(0, NULL, NULL);
}
argv[0] = cmd;
execv_git_cmd(argv);
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",
git_command, strerror(errno));
continue;
}
if (read_ref(git_path("%s", path), sha1) < 0) {
- fprintf(stderr, "%s points nowhere!", path);
+ error("%s points nowhere!", path);
continue;
}
if (!has_sha1_file(sha1)) {
- fprintf(stderr, "%s does not point to a valid "
- "commit object!", path);
+ error("%s does not point to a valid "
+ "commit object!", path);
continue;
}
retval = fn(path, sha1);
while (parents) {
struct commit *commit = parents->item;
- commit->object.flags |= UNINTERESTING;
-
- /*
- * Normally we haven't parsed the parent
- * yet, so we won't have a parent of a parent
- * here. However, it may turn out that we've
- * reached this commit some other way (where it
- * wasn't uninteresting), in which case we need
- * to mark its parents recursively too..
- */
- if (commit->parents)
- mark_parents_uninteresting(commit);
+ if (!(commit->object.flags & UNINTERESTING)) {
+ commit->object.flags |= UNINTERESTING;
+
+ /*
+ * Normally we haven't parsed the parent
+ * yet, so we won't have a parent of a parent
+ * here. However, it may turn out that we've
+ * reached this commit some other way (where it
+ * wasn't uninteresting), in which case we need
+ * to mark its parents recursively too..
+ */
+ if (commit->parents)
+ mark_parents_uninteresting(commit);
+ }
/*
* A missing commit is ok iff its parent is marked