Merge commit '77e6f5bc1009aa588a3b2235758bf5be13b23d85'

This commit is contained in:
Johannes Sixt
2007-05-19 22:22:15 +02:00
45 changed files with 904 additions and 195 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,5 @@
GIT-CFLAGS
GIT-GUI-VARS
GIT-VERSION-FILE
git
git-add
@@ -141,6 +142,7 @@ git-verify-tag
git-whatchanged
git-write-tree
git-core-*/?*
gitk-wish
gitweb/gitweb.cgi
test-chmtime
test-date

View File

@@ -65,6 +65,11 @@ install: man
$(INSTALL) -m644 $(DOC_MAN7) $(DESTDIR)$(man7dir)
../GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
$(MAKE) -C ../ GIT-VERSION-FILE
-include ../GIT-VERSION-FILE
#
# Determine "include::" file references in asciidoc files.
#
@@ -91,17 +96,25 @@ $(cmds_txt): cmd-list.perl $(MAN1_TXT)
git.7 git.html: git.txt core-intro.txt
clean:
rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html doc.dep
rm -f *.xml *.xml+ *.html *.html+ *.1 *.7 howto-index.txt howto/*.html doc.dep
rm -f $(cmds_txt)
%.html : %.txt
$(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf $(ASCIIDOC_EXTRA) $<
rm -f $@+ $@
$(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf \
$(ASCIIDOC_EXTRA) -o - $< | \
sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' >$@+
mv $@+ $@
%.1 %.7 : %.xml
xmlto -m callouts.xsl man $<
%.xml : %.txt
$(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf $<
rm -f $@+ $@
$(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf \
$(ASCIIDOC_EXTRA) -o - $< | \
sed -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' >$@+
mv $@+ $@
user-manual.xml: user-manual.txt user-manual.conf
$(ASCIIDOC) -b docbook -d book $<
@@ -132,3 +145,5 @@ install-webdoc : html
quick-install:
sh ./install-doc-quick.sh $(DOC_REF) $(mandir)
.PHONY: .FORCE-GIT-VERSION-FILE

View File

@@ -31,6 +31,25 @@ ifdef::backend-docbook[]
{title#}</example>
endif::backend-docbook[]
ifdef::doctype-manpage[]
ifdef::backend-docbook[]
[header]
template::[header-declarations]
<refentry>
<refmeta>
<refentrytitle>{mantitle}</refentrytitle>
<manvolnum>{manvolnum}</manvolnum>
<refmiscinfo class="source">Git</refmiscinfo>
<refmiscinfo class="version">@@GIT_VERSION@@</refmiscinfo>
<refmiscinfo class="manual">Git Manual</refmiscinfo>
</refmeta>
<refnamediv>
<refname>{manname}</refname>
<refpurpose>{manpurpose}</refpurpose>
</refnamediv>
endif::backend-docbook[]
endif::doctype-manpage[]
ifdef::backend-xhtml11[]
[gitlink-inlinemacro]
<a href="{target}.html">{target}{0?({0})}</a>

View File

@@ -9,7 +9,7 @@ git-fsck - Verifies the connectivity and validity of the objects in the database
SYNOPSIS
--------
[verse]
'git-fsck' [--tags] [--root] [--unreachable] [--cache]
'git-fsck' [--tags] [--root] [--unreachable] [--cache] [--no-reflogs]
[--full] [--strict] [<object>*]
DESCRIPTION
@@ -38,6 +38,12 @@ index file and all SHA1 references in .git/refs/* as heads.
Consider any object recorded in the index also as a head node for
an unreachability trace.
--no-reflogs::
Do not consider commits that are referenced only by an
entry in a reflog to be reachable. This option is meant
only to search for commits that used to be in a ref, but
now aren't, but are still in that corresponding reflog.
--full::
Check not just objects in GIT_OBJECT_DIRECTORY
($GIT_DIR/objects), but also the ones found in alternate

View File

@@ -21,11 +21,13 @@ SYNOPSIS
[ \--stdin ]
[ \--topo-order ]
[ \--parents ]
[ \--left-right ]
[ \--encoding[=<encoding>] ]
[ \--(author|committer|grep)=<pattern> ]
[ [\--objects | \--objects-edge] [ \--unpacked ] ]
[ \--pretty | \--header ]
[ \--bisect ]
[ \--bisect-vars ]
[ \--merge ]
[ \--reverse ]
[ \--walk-reflogs ]
@@ -100,6 +102,36 @@ include::pretty-formats.txt[]
Print the parents of the commit.
--left-right::
Mark which side of a symmetric diff a commit is reachable from.
Commits from the left side are prefixed with `<` and those from
the right with `>`. If combined with `--boundary`, those
commits are prefixed with `-`.
+
For example, if you have this topology:
+
-----------------------------------------------------------------------
y---b---b branch B
/ \ /
/ .
/ / \
o---x---a---a branch A
-----------------------------------------------------------------------
+
you would get an output line this:
+
-----------------------------------------------------------------------
$ git rev-list --left-right --boundary --pretty=oneline A...B
>bbbbbbb... 3rd on b
>bbbbbbb... 2nd on b
<aaaaaaa... 3rd on a
<aaaaaaa... 2nd on a
-yyyyyyy... 1st on b
-xxxxxxx... 1st on a
-----------------------------------------------------------------------
Diff Formatting
~~~~~~~~~~~~~~~
@@ -249,6 +281,18 @@ 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.
--bisect-vars::
This calculates the same as `--bisect`, but outputs text ready
to be eval'ed by the shell. These lines will assign the name of
the midpoint revision to the variable `bisect_rev`, and the
expected number of commits to be tested after `bisect_rev` is
tested to `bisect_nr`, the expected number of commits to be
tested if `bisect_rev` turns out to be good to `bisect_good`,
the expected number of commits to be tested if `bisect_rev`
turns out to be bad to `bisect_bad`, and the number of commits
we are bisecting right now to `bisect_all`.
--
Commit Ordering

View File

@@ -110,6 +110,14 @@ all:
# Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's
# MakeMaker (e.g. using ActiveState under Cygwin).
#
# Define WITH_P4IMPORT to build and install Python git-p4import script.
#
# Define NO_TCLTK if you do not want Tcl/Tk GUI.
#
# The TCLTK_PATH variable governs the location of the Tck/Tk interpreter.
# If not set it defaults to the bare 'wish'. If it is set to the empty
# string then NO_TCLTK will be forced (this is used by configure script).
#
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
@$(SHELL_PATH) ./GIT-VERSION-GEN
@@ -159,6 +167,7 @@ AR = ar
TAR = tar
INSTALL = install
RPMBUILD = rpmbuild
TCLTK_PATH = wish
# sparse is architecture-neutral, which means that we need to tell it
# explicitly what architecture to check for. Fix this up for yours..
@@ -197,9 +206,20 @@ SCRIPT_PERL = \
git-svnimport.perl git-cvsexportcommit.perl \
git-send-email.perl git-svn.perl
SCRIPT_PYTHON = \
git-p4import.py
ifdef WITH_P4IMPORT
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
$(patsubst %.py,%,$(SCRIPT_PYTHON)) \
git-status git-instaweb
else
SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
$(patsubst %.perl,%,$(SCRIPT_PERL)) \
git-status git-instaweb
endif
# ... and all the rest that could be moved out of bindir to gitexecdir
PROGRAMS = \
@@ -230,6 +250,12 @@ BUILT_INS = \
# what 'all' will build and 'install' will install, in gitexecdir
ALL_PROGRAMS = $(PROGRAMS) $(SCRIPTS)
# what 'all' will build but not install in gitexecdir
OTHER_PROGRAMS = git$X gitweb/gitweb.cgi
ifndef NO_TCLTK
OTHER_PROGRAMS += gitk-wish
endif
# Backward compatibility -- to be removed after 1.0
PROGRAMS += git-ssh-pull$X git-ssh-push$X
@@ -240,6 +266,9 @@ endif
ifndef PERL_PATH
PERL_PATH = /usr/bin/perl
endif
ifndef PYTHON_PATH
PYTHON_PATH = /usr/local/bin/python
endif
export PERL_PATH
@@ -635,6 +664,10 @@ ifdef NO_PERL_MAKEMAKER
export NO_PERL_MAKEMAKER
endif
ifeq ($(TCLTK_PATH),)
NO_TCLTK=NoThanks
endif
QUIET_SUBDIR0 = $(MAKE) -C # space to separate -C and subdir
QUIET_SUBDIR1 =
@@ -673,6 +706,8 @@ prefix_SQ = $(subst ','\'',$(prefix))
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
PYTHON_PATH_SQ = $(subst ','\'',$(PYTHON_PATH))
TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))
LIBS = $(GITLIBS) $(EXTLIBS)
@@ -688,16 +723,24 @@ export prefix gitexecdir TAR INSTALL DESTDIR SHELL_PATH template_dir
### Build rules
all: $(ALL_PROGRAMS) $(BUILT_INS) git$X gitk gitweb/gitweb.cgi
all: $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS)
all:
$(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) all
ifndef NO_TCLTK
$(QUIET_SUBDIR0)git-gui $(QUIET_SUBDIR1) TCLTK_PATH='$(TCLTK_PATH_SQ)' all
endif
$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' all
$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) NOEXECTEMPL='$(NOEXECTEMPL)'
strip: $(PROGRAMS) git$X
$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
gitk-wish: gitk GIT-GUI-VARS
$(QUIET_GEN)rm -f $@ $@+ && \
sed -e '1,3s|^exec .* "$$0"|exec $(subst |,'\|',$(TCLTK_PATH_SQ)) "$$0"|' <gitk >$@+ && \
chmod +x $@+ && \
mv -f $@+ $@
git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS) GIT-CFLAGS
$(QUIET_LINK)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \
$(ALL_CFLAGS) -o $@ $(filter %.c,$^) \
@@ -708,7 +751,7 @@ help.o: common-cmds.h
$(BUILT_INS): git$X
$(QUIET_BUILT_IN)rm -f $@ && ln git$X $@
common-cmds.h: Documentation/git-*.txt
common-cmds.h: $(wildcard Documentation/git-*.txt)
$(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@
$(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
@@ -723,6 +766,15 @@ $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
$(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak
$(patsubst %.py,%,$(SCRIPT_PYTHON)) : % : %.py
rm -f $@ $@+
sed -e '1s|#!.*/python|#!$(PYTHON_PATH_SQ)|' \
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-e 's/@@NO_CURL@@/$(NO_CURL)/g' \
$@.py >$@+
chmod +x $@+
mv $@+ $@
perl/perl.mak: GIT-CFLAGS
$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F)
@@ -876,6 +928,20 @@ GIT-CFLAGS: .FORCE-GIT-CFLAGS
echo "$$FLAGS" >GIT-CFLAGS; \
fi
### Detect Tck/Tk interpreter path changes
ifndef NO_TCLTK
TRACK_VARS = $(subst ','\'',-DTCLTK_PATH='$(TCLTK_PATH_SQ)')
GIT-GUI-VARS: .FORCE-GIT-GUI-VARS
@VARS='$(TRACK_VARS)'; \
if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
echo 1>&2 " * new Tcl/Tk interpreter location"; \
echo "$$VARS" >$@; \
fi
.PHONY: .FORCE-GIT-GUI-VARS
endif
### Testing rules
# GNU make supports exporting all variables by "export" without parameters.
@@ -917,10 +983,13 @@ install: all
$(INSTALL) -d -m755 '$(DESTDIR_SQ)$(bindir_SQ)'
$(INSTALL) -d -m755 '$(DESTDIR_SQ)$(gitexecdir_SQ)'
$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexecdir_SQ)'
$(INSTALL) git$X gitk '$(DESTDIR_SQ)$(bindir_SQ)'
$(INSTALL) git$X '$(DESTDIR_SQ)$(bindir_SQ)'
$(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install
$(MAKE) -C perl prefix='$(prefix_SQ)' install
ifndef NO_TCLTK
$(INSTALL) gitk-wish '$(DESTDIR_SQ)$(bindir_SQ)'/gitk
$(MAKE) -C git-gui install
endif
if test 'z$(bindir_SQ)' != 'z$(gitexecdir_SQ)'; \
then \
ln -f '$(DESTDIR_SQ)$(bindir_SQ)/git$X' \
@@ -996,10 +1065,13 @@ clean:
rm -f gitweb/gitweb.cgi
$(MAKE) -C Documentation/ clean
$(MAKE) -C perl clean
$(MAKE) -C git-gui clean
$(MAKE) -C templates/ clean
$(MAKE) -C t/ clean
rm -f GIT-VERSION-FILE GIT-CFLAGS
ifndef NO_TCLTK
rm -f gitk-wish
$(MAKE) -C git-gui clean
endif
rm -f GIT-VERSION-FILE GIT-CFLAGS GIT-GUI-VARS
.PHONY: all install clean strip
.PHONY: .FORCE-GIT-VERSION-FILE TAGS tags .FORCE-GIT-CFLAGS

View File

@@ -87,7 +87,7 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec)
}
/* Read the directory and prune it */
read_directory(dir, path, base, baselen);
read_directory(dir, path, base, baselen, pathspec);
if (pathspec)
prune_directory(dir, pathspec, baselen);
}
@@ -205,7 +205,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
}
for (i = 0; i < dir.nr; i++)
add_file_to_index(dir.entries[i]->name, verbose);
add_file_to_cache(dir.entries[i]->name, verbose);
if (active_cache_changed) {
if (write_cache(newfd, active_cache, active_nr) ||

View File

@@ -30,7 +30,7 @@ static int unidiff_zero;
static int p_value = 1;
static int p_value_known;
static int check_index;
static int write_index;
static int update_index;
static int cached;
static int diffstat;
static int numstat;
@@ -417,7 +417,7 @@ static int gitdiff_hdrend(const char *line, struct patch *patch)
static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name, const char *oldnew)
{
if (!orig_name && !isnull)
return find_name(line, NULL, 1, TERM_TAB);
return find_name(line, NULL, p_value, TERM_TAB);
if (orig_name) {
int len;
@@ -427,7 +427,7 @@ static char *gitdiff_verify_name(const char *line, int isnull, char *orig_name,
len = strlen(name);
if (isnull)
die("git-apply: bad git-diff - expected /dev/null, got %s on line %d", name, linenr);
another = find_name(line, NULL, 1, TERM_TAB);
another = find_name(line, NULL, p_value, TERM_TAB);
if (!another || memcmp(another, name, len))
die("git-apply: bad git-diff - inconsistent %s filename on line %d", oldnew, linenr);
free(another);
@@ -2308,7 +2308,7 @@ static void patch_stats(struct patch *patch)
static void remove_file(struct patch *patch, int rmdir_empty)
{
if (write_index) {
if (update_index) {
if (remove_file_from_cache(patch->old_name) < 0)
die("unable to remove %s from index", patch->old_name);
cache_tree_invalidate_path(active_cache_tree, patch->old_name);
@@ -2335,7 +2335,7 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned
int namelen = strlen(path);
unsigned ce_size = cache_entry_size(namelen);
if (!write_index)
if (!update_index)
return;
ce = xcalloc(1, ce_size);
@@ -2662,8 +2662,8 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
if (whitespace_error && (new_whitespace == error_on_whitespace))
apply = 0;
write_index = check_index && apply;
if (write_index && newfd < 0)
update_index = check_index && apply;
if (update_index && newfd < 0)
newfd = hold_lock_file_for_update(&lock_file,
get_index_file(), 1);
if (check_index) {
@@ -2870,7 +2870,7 @@ int cmd_apply(int argc, const char **argv, const char *unused_prefix)
whitespace_error == 1 ? "s" : "");
}
if (write_index) {
if (update_index) {
if (write_cache(newfd, active_cache, active_nr) ||
close(newfd) || commit_lock_file(&lock_file))
die("Unable to write new index file");

View File

@@ -252,6 +252,8 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
memset(&ar, 0, sizeof(ar));
tree_idx = parse_archive_args(argc, argv, &ar);
if (prefix == NULL)
prefix = setup_git_directory();
argv += tree_idx;
parse_treeish_arg(argv, &ar.args, prefix);

View File

@@ -14,6 +14,7 @@
static int show_root;
static int show_tags;
static int show_unreachable;
static int include_reflogs = 1;
static int check_full;
static int check_strict;
static int keep_cache_objects;
@@ -348,7 +349,7 @@ static int fsck_tag(struct tag *tag)
return 0;
}
static int fsck_sha1(unsigned char *sha1)
static int fsck_sha1(const unsigned char *sha1)
{
struct object *obj = parse_object(sha1);
if (!obj) {
@@ -517,7 +518,8 @@ static int fsck_handle_ref(const char *refname, const unsigned char *sha1, int f
static void get_default_heads(void)
{
for_each_ref(fsck_handle_ref, NULL);
for_each_reflog(fsck_handle_reflog, NULL);
if (include_reflogs)
for_each_reflog(fsck_handle_reflog, NULL);
/*
* Not having any default heads isn't really fatal, but
@@ -616,6 +618,10 @@ int cmd_fsck(int argc, char **argv, const char *prefix)
keep_cache_objects = 1;
continue;
}
if (!strcmp(arg, "--no-reflogs")) {
include_reflogs = 0;
continue;
}
if (!strcmp(arg, "--full")) {
check_full = 1;
continue;
@@ -648,11 +654,8 @@ int cmd_fsck(int argc, char **argv, const char *prefix)
for (p = packed_git; p; p = p->next) {
uint32_t i, num = num_packed_objects(p);
for (i = 0; i < num; i++) {
unsigned char sha1[20];
nth_packed_object_sha1(p, i, sha1);
fsck_sha1(sha1);
}
for (i = 0; i < num; i++)
fsck_sha1(nth_packed_object_sha1(p, i));
}
}

View File

@@ -216,7 +216,7 @@ static void show_files(struct dir_struct *dir, const char *prefix)
if (baselen)
path = base = prefix;
read_directory(dir, path, base, baselen);
read_directory(dir, path, base, baselen, pathspec);
if (show_others)
show_other_files(dir);
if (show_killed)

View File

@@ -273,7 +273,7 @@ int cmd_mv(int argc, const char **argv, const char *prefix)
for (i = 0; i < added.nr; i++) {
const char *path = added.items[i].path;
add_file_to_index(path, verbose);
add_file_to_cache(path, verbose);
}
for (i = 0; i < deleted.nr; i++) {

View File

@@ -222,7 +222,7 @@ static const unsigned char *find_packed_object_name(struct packed_git *p,
off_t ofs)
{
struct revindex_entry *entry = find_packed_object(p, ofs);
return ((unsigned char *)p->index_data) + 4 * 256 + 24 * entry->nr + 4;
return nth_packed_object_sha1(p, entry->nr);
}
static void *delta_against(void *buf, unsigned long size, struct object_entry *entry)

View File

@@ -117,10 +117,13 @@ static int handle_file(const char *path,
else if (!prefixcmp(buf, "======="))
hunk = 2;
else if (!prefixcmp(buf, ">>>>>>> ")) {
int one_is_longer = (one->nr > two->nr);
int common_len = one_is_longer ? two->nr : one->nr;
int cmp = memcmp(one->ptr, two->ptr, common_len);
hunk_no++;
hunk = 0;
if (memcmp(one->ptr, two->ptr, one->nr < two->nr ?
one->nr : two->nr) > 0) {
if ((cmp > 0) || ((cmp == 0) && one_is_longer)) {
struct buffer *swap = one;
one = two;
two = swap;

View File

@@ -35,8 +35,10 @@ static const char rev_list_usage[] =
" --header | --pretty\n"
" --abbrev=nr | --no-abbrev\n"
" --abbrev-commit\n"
" --left-right\n"
" special purpose:\n"
" --bisect"
" --bisect\n"
" --bisect-vars"
;
static struct rev_info revs;
@@ -168,38 +170,273 @@ static void clear_distance(struct commit_list *list)
}
}
static struct commit_list *find_bisection(struct commit_list *list)
{
int nr, closest;
struct commit_list *p, *best;
#define DEBUG_BISECT 0
nr = 0;
p = list;
while (p) {
if (!revs.prune_fn || (p->item->object.flags & TREECHANGE))
nr++;
p = p->next;
static inline int weight(struct commit_list *elem)
{
return *((int*)(elem->item->util));
}
static inline void weight_set(struct commit_list *elem, int weight)
{
*((int*)(elem->item->util)) = weight;
}
static int count_interesting_parents(struct commit *commit)
{
struct commit_list *p;
int count;
for (count = 0, p = commit->parents; p; p = p->next) {
if (p->item->object.flags & UNINTERESTING)
continue;
count++;
}
closest = -1;
best = list;
return count;
}
static inline int halfway(struct commit_list *p, int distance, int nr)
{
/*
* Don't short-cut something we are not going to return!
*/
if (revs.prune_fn && !(p->item->object.flags & TREECHANGE))
return 0;
if (DEBUG_BISECT)
return 0;
/*
* 2 and 3 are halfway of 5.
* 3 is halfway of 6 but 2 and 4 are not.
*/
distance *= 2;
switch (distance - nr) {
case -1: case 0: case 1:
return 1;
default:
return 0;
}
}
#if !DEBUG_BISECT
#define show_list(a,b,c,d) do { ; } while (0)
#else
static void show_list(const char *debug, int counted, int nr,
struct commit_list *list)
{
struct commit_list *p;
fprintf(stderr, "%s (%d/%d)\n", debug, counted, nr);
for (p = list; p; p = p->next) {
int distance;
struct commit_list *pp;
struct commit *commit = p->item;
unsigned flags = commit->object.flags;
enum object_type type;
unsigned long size;
char *buf = read_sha1_file(commit->object.sha1, &type, &size);
char *ep, *sp;
if (revs.prune_fn && !(p->item->object.flags & TREECHANGE))
fprintf(stderr, "%c%c%c ",
(flags & TREECHANGE) ? 'T' : ' ',
(flags & UNINTERESTING) ? 'U' : ' ',
(flags & COUNTED) ? 'C' : ' ');
if (commit->util)
fprintf(stderr, "%3d", weight(p));
else
fprintf(stderr, "---");
fprintf(stderr, " %.*s", 8, sha1_to_hex(commit->object.sha1));
for (pp = commit->parents; pp; pp = pp->next)
fprintf(stderr, " %.*s", 8,
sha1_to_hex(pp->item->object.sha1));
sp = strstr(buf, "\n\n");
if (sp) {
sp += 2;
for (ep = sp; *ep && *ep != '\n'; ep++)
;
fprintf(stderr, " %.*s", (int)(ep - sp), sp);
}
fprintf(stderr, "\n");
}
}
#endif /* DEBUG_BISECT */
/*
* zero or positive weight is the number of interesting commits it can
* reach, including itself. Especially, weight = 0 means it does not
* reach any tree-changing commits (e.g. just above uninteresting one
* but traversal is with pathspec).
*
* weight = -1 means it has one parent and its distance is yet to
* be computed.
*
* weight = -2 means it has more than one parent and its distance is
* unknown. After running count_distance() first, they will get zero
* or positive distance.
*/
static struct commit_list *find_bisection(struct commit_list *list,
int *reaches, int *all)
{
int n, nr, on_list, counted, distance;
struct commit_list *p, *best, *next, *last;
int *weights;
show_list("bisection 2 entry", 0, 0, list);
/*
* Count the number of total and tree-changing items on the
* list, while reversing the list.
*/
for (nr = on_list = 0, last = NULL, p = list;
p;
p = next) {
unsigned flags = p->item->object.flags;
next = p->next;
if (flags & UNINTERESTING)
continue;
p->next = last;
last = p;
if (!revs.prune_fn || (flags & TREECHANGE))
nr++;
on_list++;
}
list = last;
show_list("bisection 2 sorted", 0, nr, list);
*all = nr;
weights = xcalloc(on_list, sizeof(int*));
counted = 0;
for (n = 0, p = list; p; p = p->next) {
struct commit *commit = p->item;
unsigned flags = commit->object.flags;
p->item->util = &weights[n++];
switch (count_interesting_parents(commit)) {
case 0:
if (!revs.prune_fn || (flags & TREECHANGE)) {
weight_set(p, 1);
counted++;
show_list("bisection 2 count one",
counted, nr, list);
}
/*
* otherwise, it is known not to reach any
* tree-changing commit and gets weight 0.
*/
break;
case 1:
weight_set(p, -1);
break;
default:
weight_set(p, -2);
break;
}
}
show_list("bisection 2 initialize", counted, nr, list);
/*
* If you have only one parent in the resulting set
* then you can reach one commit more than that parent
* can reach. So we do not have to run the expensive
* count_distance() for single strand of pearls.
*
* However, if you have more than one parents, you cannot
* just add their distance and one for yourself, since
* they usually reach the same ancestor and you would
* end up counting them twice that way.
*
* So we will first count distance of merges the usual
* way, and then fill the blanks using cheaper algorithm.
*/
for (p = list; p; p = p->next) {
if (p->item->object.flags & UNINTERESTING)
continue;
n = weight(p);
if (n != -2)
continue;
distance = count_distance(p);
clear_distance(list);
weight_set(p, distance);
/* Does it happen to be at exactly half-way? */
if (halfway(p, distance, nr)) {
p->next = NULL;
*reaches = distance;
free(weights);
return p;
}
counted++;
}
show_list("bisection 2 count_distance", counted, nr, list);
while (counted < nr) {
for (p = list; p; p = p->next) {
struct commit_list *q;
unsigned flags = p->item->object.flags;
if (0 <= weight(p))
continue;
for (q = p->item->parents; q; q = q->next) {
if (q->item->object.flags & UNINTERESTING)
continue;
if (0 <= weight(q))
break;
}
if (!q)
continue;
/*
* weight for p is unknown but q is known.
* add one for p itself if p is to be counted,
* otherwise inherit it from q directly.
*/
if (!revs.prune_fn || (flags & TREECHANGE)) {
weight_set(p, weight(q)+1);
counted++;
show_list("bisection 2 count one",
counted, nr, list);
}
else
weight_set(p, weight(q));
/* Does it happen to be at exactly half-way? */
distance = weight(p);
if (halfway(p, distance, nr)) {
p->next = NULL;
*reaches = distance;
free(weights);
return p;
}
}
}
show_list("bisection 2 counted all", counted, nr, list);
/* Then find the best one */
counted = -1;
best = list;
for (p = list; p; p = p->next) {
unsigned flags = p->item->object.flags;
if (revs.prune_fn && !(flags & TREECHANGE))
continue;
distance = weight(p);
if (nr - distance < distance)
distance = nr - distance;
if (distance > closest) {
if (distance > counted) {
best = p;
closest = distance;
counted = distance;
*reaches = weight(p);
}
}
if (best)
best->next = NULL;
free(weights);
return best;
}
@@ -225,6 +462,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
struct commit_list *list;
int i;
int read_from_stdin = 0;
int bisect_show_vars = 0;
git_config(git_default_config);
init_revisions(&revs, prefix);
@@ -247,6 +485,11 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
bisect_list = 1;
continue;
}
if (!strcmp(arg, "--bisect-vars")) {
bisect_list = 1;
bisect_show_vars = 1;
continue;
}
if (!strcmp(arg, "--stdin")) {
if (read_from_stdin++)
die("--stdin given twice?");
@@ -285,8 +528,39 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
if (revs.tree_objects)
mark_edges_uninteresting(revs.commits, &revs, show_edge);
if (bisect_list)
revs.commits = find_bisection(revs.commits);
if (bisect_list) {
int reaches = reaches, all = all;
revs.commits = find_bisection(revs.commits, &reaches, &all);
if (bisect_show_vars) {
int cnt;
if (!revs.commits)
return 1;
/*
* revs.commits can reach "reaches" commits among
* "all" commits. If it is good, then there are
* (all-reaches) commits left to be bisected.
* On the other hand, if it is bad, then the set
* to bisect is "reaches".
* A bisect set of size N has (N-1) commits further
* to test, as we already know one bad one.
*/
cnt = all-reaches;
if (cnt < reaches)
cnt = reaches;
printf("bisect_rev=%s\n"
"bisect_nr=%d\n"
"bisect_good=%d\n"
"bisect_bad=%d\n"
"bisect_all=%d\n",
sha1_to_hex(revs.commits->item->object.sha1),
cnt - 1,
all - reaches - 1,
reaches - 1,
all);
return 0;
}
}
traverse_commit_list(&revs, show_commit, show_object);

View File

@@ -60,7 +60,7 @@ static int mark_valid(const char *path)
return -1;
}
static int add_file_to_cache(const char *path)
static int process_file(const char *path)
{
int size, namelen, option, status;
struct cache_entry *ce;
@@ -210,7 +210,7 @@ static void update_one(const char *path, const char *prefix, int prefix_length)
report("remove '%s'", path);
goto free_return;
}
if (add_file_to_cache(p))
if (process_file(p))
die("Unable to process file %s", path);
report("add '%s'", path);
free_return:

View File

@@ -128,7 +128,6 @@ static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned in
extern struct cache_entry **active_cache;
extern unsigned int active_nr, active_alloc, active_cache_changed;
extern struct cache_tree *active_cache_tree;
extern int cache_errno;
enum object_type {
OBJ_BAD = -1,
@@ -188,7 +187,7 @@ extern int add_cache_entry(struct cache_entry *ce, int option);
extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
extern int remove_cache_entry_at(int pos);
extern int remove_file_from_cache(const char *path);
extern int add_file_to_index(const char *path, int verbose);
extern int add_file_to_cache(const char *path, int verbose);
extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
extern int ce_match_stat(struct cache_entry *ce, struct stat *st, int);
extern int ce_modified(struct cache_entry *ce, struct stat *st, int);
@@ -429,7 +428,7 @@ extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t
extern void unuse_pack(struct pack_window **);
extern struct packed_git *add_packed_git(const char *, int, int);
extern uint32_t num_packed_objects(const struct packed_git *p);
extern int nth_packed_object_sha1(const struct packed_git *, uint32_t, unsigned char*);
extern const unsigned char *nth_packed_object_sha1(const struct packed_git *, uint32_t);
extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *);
extern void *unpack_entry(struct packed_git *, off_t, enum object_type *, unsigned long *);
extern unsigned long unpack_object_header_gently(const unsigned char *buf, unsigned long len, enum object_type *type, unsigned long *sizep);

View File

@@ -918,8 +918,8 @@ int git_config_rename_section(const char *old_name, const char *new_name)
}
if (!(config_file = fopen(config_filename, "rb"))) {
ret = error("Could not open config file!");
goto out;
/* no config file means nothing to rename, no error */
goto unlock_and_out;
}
while (fgets(buf, sizeof(buf), config_file)) {
@@ -953,6 +953,7 @@ int git_config_rename_section(const char *old_name, const char *new_name)
}
}
fclose(config_file);
unlock_and_out:
if (close(out_fd) || commit_lock_file(lock) < 0)
ret = error("Cannot commit config file!");
out:

View File

@@ -6,6 +6,7 @@ CFLAGS = @CFLAGS@
AR = @AR@
TAR = @TAR@
#INSTALL = @INSTALL@ # needs install-sh or install.sh in sources
TCLTK_PATH = @TCLTK_PATH@
prefix = @prefix@
exec_prefix = @exec_prefix@

View File

@@ -75,6 +75,14 @@ GIT_ARG_SET_PATH(shell)
# Define PERL_PATH to provide path to Perl.
GIT_ARG_SET_PATH(perl)
#
# Declare the with-tcltk/without-tcltk options.
AC_ARG_WITH(tcltk,
AS_HELP_STRING([--with-tcltk],[use Tcl/Tk GUI (default is YES)])
AS_HELP_STRING([],[ARG is the full path to the Tcl/Tk interpreter.])
AS_HELP_STRING([],[Bare --with-tcltk will make the GUI part only if])
AS_HELP_STRING([],[Tcl/Tk interpreter will be found in a system.]),\
GIT_PARSE_WITH(tcltk))
#
## Checks for programs.
@@ -84,6 +92,22 @@ AC_PROG_CC([cc gcc])
#AC_PROG_INSTALL # needs install-sh or install.sh in sources
AC_CHECK_TOOL(AR, ar, :)
AC_CHECK_PROGS(TAR, [gtar tar])
# TCLTK_PATH will be set to some value if we want Tcl/Tk
# or will be empty otherwise.
if test -z "$NO_TCLTK"; then
if test "$with_tcltk" = ""; then
# No Tcl/Tk switches given. Do not check for Tcl/Tk, use bare 'wish'.
TCLTK_PATH=wish
AC_SUBST(TCLTK_PATH)
elif test "$with_tcltk" = "yes"; then
# Tcl/Tk check requested.
AC_CHECK_PROGS(TCLTK_PATH, [wish], )
else
AC_MSG_RESULT([Using Tcl/Tk interpreter $with_tcltk])
TCLTK_PATH="$with_tcltk"
AC_SUBST(TCLTK_PATH)
fi
fi
## Checks for libraries.
AC_MSG_NOTICE([CHECKS for libraries])

View File

@@ -11,8 +11,8 @@ emacsdir = $(prefix)/share/emacs/site-lisp
all: $(ELC)
install: all
$(INSTALL) -d $(emacsdir)
$(INSTALL_ELC) $(ELC) $(emacsdir)
$(INSTALL) -d $(DESTDIR)$(emacsdir)
$(INSTALL_ELC) $(ELC) $(DESTDIR)$(emacsdir)
%.elc: %.el
$(EMACS) -batch -f batch-byte-compile $<

View File

@@ -8,8 +8,8 @@
;; License: GPL
;; Keywords: git, version control, release management
;;
;; Compatibility: Emacs21
;; Compatibility: Emacs21, Emacs22 and EmacsCVS
;; Git 1.5 and up
;; This file is *NOT* part of GNU Emacs.
;; This file is distributed under the same terms as GNU Emacs.
@@ -61,8 +61,9 @@
;;; Compatibility:
;;
;; It requires GNU Emacs 21. If you'are using Emacs 20, try
;; changing this:
;; It requires GNU Emacs 21 or later and Git 1.5.0 and up
;;
;; If you'are using Emacs 20, try changing this:
;;
;; (overlay-put ovl 'face (list :background
;; (cdr (assq 'color (cddddr info)))))
@@ -77,30 +78,51 @@
;;
;;; Code:
(require 'cl) ; to use `push', `pop'
(eval-when-compile (require 'cl)) ; to use `push', `pop'
(defun color-scale (l)
(let* ((colors ())
r g b)
(setq r l)
(while r
(setq g l)
(while g
(setq b l)
(while b
(push (concat "#" (car r) (car g) (car b)) colors)
(pop b))
(pop g))
(pop r))
colors))
(defun git-blame-color-scale (&rest elements)
"Given a list, returns a list of triples formed with each
elements of the list.
a b => bbb bba bab baa abb aba aaa aab"
(let (result)
(dolist (a elements)
(dolist (b elements)
(dolist (c elements)
(setq result (cons (format "#%s%s%s" a b c) result)))))
result))
;; (git-blame-color-scale "0c" "04" "24" "1c" "2c" "34" "14" "3c") =>
;; ("#3c3c3c" "#3c3c14" "#3c3c34" "#3c3c2c" "#3c3c1c" "#3c3c24"
;; "#3c3c04" "#3c3c0c" "#3c143c" "#3c1414" "#3c1434" "#3c142c" ...)
(defmacro git-blame-random-pop (l)
"Select a random element from L and returns it. Also remove
selected element from l."
;; only works on lists with unique elements
`(let ((e (elt ,l (random (length ,l)))))
(setq ,l (remove e ,l))
e))
(defvar git-blame-dark-colors
(color-scale '("0c" "04" "24" "1c" "2c" "34" "14" "3c")))
(git-blame-color-scale "0c" "04" "24" "1c" "2c" "34" "14" "3c")
"*List of colors (format #RGB) to use in a dark environment.
To check out the list, evaluate (list-colors-display git-blame-dark-colors).")
(defvar git-blame-light-colors
(color-scale '("c4" "d4" "cc" "dc" "f4" "e4" "fc" "ec")))
(git-blame-color-scale "c4" "d4" "cc" "dc" "f4" "e4" "fc" "ec")
"*List of colors (format #RGB) to use in a light environment.
(defvar git-blame-ancient-color "dark green")
To check out the list, evaluate (list-colors-display git-blame-light-colors).")
(defvar git-blame-colors '()
"Colors used by git-blame. The list is built once when activating git-blame
minor mode.")
(defvar git-blame-ancient-color "dark green"
"*Color to be used for ancient commit.")
(defvar git-blame-autoupdate t
"*Automatically update the blame display while editing")
@@ -125,41 +147,64 @@
"A queue of update requests")
(make-variable-buffer-local 'git-blame-update-queue)
;; FIXME: docstrings
(defvar git-blame-file nil)
(defvar git-blame-current nil)
(defvar git-blame-mode nil)
(make-variable-buffer-local 'git-blame-mode)
(unless (assq 'git-blame-mode minor-mode-alist)
(setq minor-mode-alist
(cons (list 'git-blame-mode " blame")
minor-mode-alist)))
(defvar git-blame-mode-line-string " blame"
"String to display on the mode line when git-blame is active.")
(or (assq 'git-blame-mode minor-mode-alist)
(setq minor-mode-alist
(cons '(git-blame-mode git-blame-mode-line-string) minor-mode-alist)))
;;;###autoload
(defun git-blame-mode (&optional arg)
"Minor mode for displaying Git blame"
"Toggle minor mode for displaying Git blame
With prefix ARG, turn the mode on if ARG is positive."
(interactive "P")
(if arg
(setq git-blame-mode (eq arg 1))
(setq git-blame-mode (not git-blame-mode)))
(cond
((null arg)
(if git-blame-mode (git-blame-mode-off) (git-blame-mode-on)))
((> (prefix-numeric-value arg) 0) (git-blame-mode-on))
(t (git-blame-mode-off))))
(defun git-blame-mode-on ()
"Turn on git-blame mode.
See also function `git-blame-mode'."
(make-local-variable 'git-blame-colors)
(if git-blame-autoupdate
(add-hook 'after-change-functions 'git-blame-after-change nil t)
(remove-hook 'after-change-functions 'git-blame-after-change t))
(git-blame-cleanup)
(if git-blame-mode
(progn
(let ((bgmode (cdr (assoc 'background-mode (frame-parameters)))))
(if (eq bgmode 'dark)
(setq git-blame-colors git-blame-dark-colors)
(setq git-blame-colors git-blame-light-colors)))
(setq git-blame-cache (make-hash-table :test 'equal))
(git-blame-run))
(cancel-timer git-blame-idle-timer)))
(let ((bgmode (cdr (assoc 'background-mode (frame-parameters)))))
(if (eq bgmode 'dark)
(setq git-blame-colors git-blame-dark-colors)
(setq git-blame-colors git-blame-light-colors)))
(setq git-blame-cache (make-hash-table :test 'equal))
(setq git-blame-mode t)
(git-blame-run))
(defun git-blame-mode-off ()
"Turn off git-blame mode.
See also function `git-blame-mode'."
(git-blame-cleanup)
(if git-blame-idle-timer (cancel-timer git-blame-idle-timer))
(setq git-blame-mode nil))
;;;###autoload
(defun git-reblame ()
"Recalculate all blame information in the current buffer"
(unless git-blame-mode
(error "git-blame is not active"))
(interactive)
(unless git-blame-mode
(error "Git-blame is not active"))
(git-blame-cleanup)
(git-blame-run))
@@ -275,7 +320,6 @@
(t
nil)))
(defun git-blame-new-commit (hash src-line res-line num-lines)
(save-excursion
(set-buffer git-blame-file)
@@ -283,9 +327,11 @@
(inhibit-point-motion-hooks t)
(inhibit-modification-hooks t))
(when (not info)
(let ((color (pop git-blame-colors)))
(unless color
(setq color git-blame-ancient-color))
;; Assign a random color to each new commit info
;; Take care not to select the same color multiple times
(let ((color (if git-blame-colors
(git-blame-random-pop git-blame-colors)
git-blame-ancient-color)))
(setq info (list hash src-line res-line num-lines
(git-describe-commit hash)
(cons 'color color))))

13
diff.c
View File

@@ -812,7 +812,12 @@ static void show_stats(struct diffstat_t* data, struct diff_options *options)
if (data->files[i]->is_binary) {
show_name(prefix, name, len, reset, set);
printf(" Bin\n");
printf(" Bin ");
printf("%s%d%s", del_c, deleted, reset);
printf(" -> ");
printf("%s%d%s", add_c, added, reset);
printf(" bytes");
printf("\n");
goto free_diffstat_file;
}
else if (data->files[i]->is_unmerged) {
@@ -1186,9 +1191,11 @@ static void builtin_diffstat(const char *name_a, const char *name_b,
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
die("unable to read files to diff");
if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2))
if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2)) {
data->is_binary = 1;
else {
data->added = mf2.size;
data->deleted = mf1.size;
} else {
/* Crazy xdl interfaces.. */
xpparam_t xpp;
xdemitconf_t xecfg;

96
dir.c
View File

@@ -8,6 +8,11 @@
#include "cache.h"
#include "dir.h"
struct path_simplify {
int len;
const char *path;
};
int common_prefix(const char **pathspec)
{
const char *path, *slash, *next;
@@ -292,6 +297,31 @@ static int dir_exists(const char *dirname, int len)
return !strncmp(active_cache[pos]->name, dirname, len);
}
/*
* This is an inexact early pruning of any recursive directory
* reading - if the path cannot possibly be in the pathspec,
* return true, and we'll skip it early.
*/
static int simplify_away(const char *path, int pathlen, const struct path_simplify *simplify)
{
if (simplify) {
for (;;) {
const char *match = simplify->path;
int len = simplify->len;
if (!match)
break;
if (len > pathlen)
len = pathlen;
if (!memcmp(path, match, len))
return 0;
simplify++;
}
return 1;
}
return 0;
}
/*
* Read a directory tree. We currently ignore anything but
* directories, regular files and symlinks. That's because git
@@ -301,7 +331,7 @@ static int dir_exists(const char *dirname, int len)
* Also, we ignore the name ".git" (even if it is not a directory).
* That likely will not change.
*/
static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only)
static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only, const struct path_simplify *simplify)
{
DIR *fdir = opendir(path);
int contents = 0;
@@ -324,6 +354,8 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
continue;
len = strlen(de->d_name);
memcpy(fullname + baselen, de->d_name, len+1);
if (simplify_away(fullname, baselen + len, simplify))
continue;
if (excluded(dir, fullname) != dir->show_ignored) {
if (!dir->show_ignored || DTYPE(de) != DT_DIR) {
continue;
@@ -350,13 +382,13 @@ static int read_directory_recursive(struct dir_struct *dir, const char *path, co
if (dir->hide_empty_directories &&
!read_directory_recursive(dir,
fullname, fullname,
baselen + len, 1))
baselen + len, 1, simplify))
continue;
break;
}
contents += read_directory_recursive(dir,
fullname, fullname, baselen + len, 0);
fullname, fullname, baselen + len, 0, simplify);
continue;
case DT_REG:
case DT_LNK:
@@ -386,8 +418,61 @@ static int cmp_name(const void *p1, const void *p2)
e2->name, e2->len);
}
int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen)
/*
* Return the length of the "simple" part of a path match limiter.
*/
static int simple_length(const char *match)
{
const char special[256] = {
[0] = 1, ['?'] = 1,
['\\'] = 1, ['*'] = 1,
['['] = 1
};
int len = -1;
for (;;) {
unsigned char c = *match++;
len++;
if (special[c])
return len;
}
}
static struct path_simplify *create_simplify(const char **pathspec)
{
int nr, alloc = 0;
struct path_simplify *simplify = NULL;
if (!pathspec)
return NULL;
for (nr = 0 ; ; nr++) {
const char *match;
if (nr >= alloc) {
alloc = alloc_nr(alloc);
simplify = xrealloc(simplify, alloc * sizeof(*simplify));
}
match = *pathspec++;
if (!match)
break;
simplify[nr].path = match;
simplify[nr].len = simple_length(match);
}
simplify[nr].path = NULL;
simplify[nr].len = 0;
return simplify;
}
static void free_simplify(struct path_simplify *simplify)
{
if (simplify)
free(simplify);
}
int read_directory(struct dir_struct *dir, const char *path, const char *base, int baselen, const char **pathspec)
{
struct path_simplify *simplify = create_simplify(pathspec);
/*
* Make sure to do the per-directory exclude for all the
* directories leading up to our base.
@@ -414,7 +499,8 @@ int read_directory(struct dir_struct *dir, const char *path, const char *base, i
}
}
read_directory_recursive(dir, path, base, baselen, 0);
read_directory_recursive(dir, path, base, baselen, 0, simplify);
free_simplify(simplify);
qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name);
return dir->nr;
}

2
dir.h
View File

@@ -48,7 +48,7 @@ extern int common_prefix(const char **pathspec);
#define MATCHED_EXACTLY 3
extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen);
extern int read_directory(struct dir_struct *, const char *path, const char *base, int baselen, const char **pathspec);
extern int push_exclude_per_directory(struct dir_struct *, const char *, int);
extern void pop_exclude_per_directory(struct dir_struct *, int);

View File

@@ -12,7 +12,7 @@ fi
laf="$GIT_DIR/lost-found"
rm -fr "$laf" && mkdir -p "$laf/commit" "$laf/other" || exit
git fsck --full |
git fsck --full --no-reflogs |
while read dangling type sha1
do
case "$dangling" in

View File

@@ -33,7 +33,7 @@ use Carp qw/croak/;
use IO::File qw//;
use File::Basename qw/dirname basename/;
use File::Path qw/mkpath/;
use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev pass_through/;
use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/;
use IPC::Open3;
use Git;
@@ -168,6 +168,7 @@ for (my $i = 0; $i < @ARGV; $i++) {
my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
read_repo_config(\%opts);
Getopt::Long::Configure('pass_through') if $cmd eq 'log';
my $rv = GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version,
'minimize-connections' => \$Git::SVN::Migration::_minimize,
'id|i=s' => \$Git::SVN::default_ref_id,
@@ -229,6 +230,8 @@ Usage: $0 <command> [options] [arguments]\n
next if /^multi-/; # don't show deprecated commands
print $fd ' ',pack('A17',$_),$cmd{$_}->[1],"\n";
foreach (keys %{$cmd{$_}->[2]}) {
# mixed-case options are for .git/config only
next if /[A-Z]/ && /^[a-z]+$/i;
# prints out arguments as they should be passed:
my $x = s#[:=]s$## ? '<arg>' : s#[:=]i$## ? '<num>' : '';
print $fd ' ' x 21, join(', ', map { length $_ > 1 ?

2
git.c
View File

@@ -230,7 +230,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "add", cmd_add, RUN_SETUP | NOT_BARE },
{ "annotate", cmd_annotate, USE_PAGER },
{ "apply", cmd_apply },
{ "archive", cmd_archive, RUN_SETUP },
{ "archive", cmd_archive },
{ "blame", cmd_blame, RUN_SETUP },
{ "branch", cmd_branch, RUN_SETUP },
{ "bundle", cmd_bundle },

View File

@@ -1,4 +1,7 @@
# Pass --without docs to rpmbuild if you don't want the documentation
%define python_path /usr/bin/python
Name: git
Version: @@VERSION@@
Release: 1%{?dist}
@@ -9,7 +12,7 @@ URL: http://kernel.org/pub/software/scm/git/
Source: http://kernel.org/pub/software/scm/git/%{name}-%{version}.tar.gz
BuildRequires: zlib-devel >= 1.2, openssl-devel, curl-devel, expat-devel %{!?_without_docs:, xmlto, asciidoc > 6.0.3}
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Requires: git-core, git-svn, git-cvs, git-arch, git-email, gitk, git-gui, perl-Git
Requires: git-core, git-svn, git-cvs, git-arch, git-email, gitk, git-gui, git-p4, perl-Git
%description
Git is a fast, scalable, distributed revision control system with an
@@ -50,6 +53,13 @@ Requires: git-core = %{version}-%{release}, tla
%description arch
Git tools for importing Arch repositories.
%package p4
Summary: Git tools for importing Perforce repositories
Group: Development/Tools
Requires: git-core = %{version}-%{release}, python
%description p4
Git tools for importing Perforce repositories.
%package email
Summary: Git tools for sending email
Group: Development/Tools
@@ -85,23 +95,23 @@ Perl interface to Git
%setup -q
%build
make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_OWN_SUBPROCESS_PY=YesPlease \
prefix=%{_prefix} all %{!?_without_docs: doc}
make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_P4IMPORT=YesPlease \
prefix=%{_prefix} PYTHON_PATH=%{python_path} all %{!?_without_docs: doc}
%install
rm -rf $RPM_BUILD_ROOT
make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" DESTDIR=$RPM_BUILD_ROOT \
WITH_OWN_SUBPROCESS_PY=YesPlease \
prefix=%{_prefix} mandir=%{_mandir} INSTALLDIRS=vendor \
install %{!?_without_docs: install-doc}
WITH_P4IMPORT=YesPlease prefix=%{_prefix} mandir=%{_mandir} \
PYTHON_PATH=%{python_path} \
INSTALLDIRS=vendor install %{!?_without_docs: install-doc}
find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';'
find $RPM_BUILD_ROOT -type f -name '*.bs' -empty -exec rm -f {} ';'
find $RPM_BUILD_ROOT -type f -name perllocal.pod -exec rm -f {} ';'
(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@) > bin-man-doc-files
(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "p4import|archimport|svn|cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@) > bin-man-doc-files
(find $RPM_BUILD_ROOT%{perl_vendorlib} -type f | sed -e s@^$RPM_BUILD_ROOT@@) >> perl-files
%if %{!?_without_docs:1}0
(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "p4import|archimport|svn|git-cvs|email|gitk|git-gui|git-citool" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
%else
rm -rf $RPM_BUILD_ROOT%{_mandir}
%endif
@@ -133,6 +143,13 @@ rm -rf $RPM_BUILD_ROOT
%{!?_without_docs: %{_mandir}/man1/git-archimport.1*}
%{!?_without_docs: %doc Documentation/git-archimport.html }
%files p4
%defattr(-,root,root)
%doc Documentation/git-p4import.txt
%{_bindir}/git-p4import
%{!?_without_docs: %{_mandir}/man1/git-p4import.1*}
%{!?_without_docs: %doc Documentation/git-p4import.html }
%files email
%defattr(-,root,root)
%doc Documentation/*email*.txt
@@ -167,6 +184,9 @@ rm -rf $RPM_BUILD_ROOT
%{!?_without_docs: %doc Documentation/*.html }
%changelog
* Tue Mar 27 2007 Eygene Ryabinkin <rea-git@codelabs.ru>
- Added the git-p4 package: Perforce import stuff.
* Mon Feb 13 2007 Nicolas Pitre <nico@cam.org>
- Update core package description (Git isn't as stupid as it used to be)

View File

@@ -19,7 +19,7 @@ use File::Basename qw(basename);
binmode STDOUT, ':utf8';
BEGIN {
CGI->compile() if $ENV{MOD_PERL};
CGI->compile() if $ENV{'MOD_PERL'};
}
our $cgi = new CGI;
@@ -1800,7 +1800,7 @@ EOF
$cgi->hidden(-name => "a") . "\n" .
$cgi->hidden(-name => "h") . "\n" .
$cgi->popup_menu(-name => 'st', -default => 'commit',
-values => ['commit', 'author', 'committer', 'pickaxe']) .
-values => ['commit', 'author', 'committer', 'pickaxe']) .
$cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) .
" search:\n",
$cgi->textfield(-name => "s", -value => $searchtext) . "\n" .
@@ -1870,16 +1870,16 @@ sub git_print_page_nav {
my %arg = map { $_ => {action=>$_} } @navs;
if (defined $head) {
for (qw(commit commitdiff)) {
$arg{$_}{hash} = $head;
$arg{$_}{'hash'} = $head;
}
if ($current =~ m/^(tree | log | shortlog | commit | commitdiff | search)$/x) {
for (qw(shortlog log)) {
$arg{$_}{hash} = $head;
$arg{$_}{'hash'} = $head;
}
}
}
$arg{tree}{hash} = $treehead if defined $treehead;
$arg{tree}{hash_base} = $treebase if defined $treebase;
$arg{'tree'}{'hash'} = $treehead if defined $treehead;
$arg{'tree'}{'hash_base'} = $treebase if defined $treebase;
print "<div class=\"page_nav\">\n" .
(join " | ",
@@ -1927,9 +1927,9 @@ sub git_print_header_div {
my ($action, $title, $hash, $hash_base) = @_;
my %args = ();
$args{action} = $action;
$args{hash} = $hash if $hash;
$args{hash_base} = $hash_base if $hash_base;
$args{'action'} = $action;
$args{'hash'} = $hash if $hash;
$args{'hash_base'} = $hash_base if $hash_base;
print "<div class=\"header\">\n" .
$cgi->a({-href => href(%args), -class => "title"},
@@ -3095,7 +3095,7 @@ sub git_summary {
git_project_list_body(\@forklist, undef, 0, 15,
$#forklist <= 15 ? undef :
$cgi->a({-href => href(action=>"forks")}, "..."),
'noheader');
'noheader');
}
git_footer_html();
@@ -3202,7 +3202,7 @@ HTML
my $rev = substr($full_rev, 0, 8);
my $author = $meta->{'author'};
my %date = parse_date($meta->{'author-time'},
$meta->{'author-tz'});
$meta->{'author-tz'});
my $date = $date{'iso-tz'};
if ($group_size) {
$current_color = ++$current_color % $num_colors;
@@ -3214,9 +3214,9 @@ HTML
print " rowspan=\"$group_size\"" if ($group_size > 1);
print ">";
print $cgi->a({-href => href(action=>"commit",
hash=>$full_rev,
file_name=>$file_name)},
esc_html($rev));
hash=>$full_rev,
file_name=>$file_name)},
esc_html($rev));
print "</td>\n";
}
open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^")
@@ -3225,13 +3225,13 @@ HTML
close $dd;
chomp($parent_commit);
my $blamed = href(action => 'blame',
file_name => $meta->{'filename'},
hash_base => $parent_commit);
file_name => $meta->{'filename'},
hash_base => $parent_commit);
print "<td class=\"linenr\">";
print $cgi->a({ -href => "$blamed#l$orig_lineno",
-id => "l$lineno",
-class => "linenr" },
esc_html($lineno));
-id => "l$lineno",
-class => "linenr" },
esc_html($lineno));
print "</td>";
print "<td class=\"pre\">" . esc_html($data) . "</td>\n";
print "</tr>\n";
@@ -3621,7 +3621,7 @@ sub git_snapshot {
my $name = $project;
$name =~ s/\047/\047\\\047\047/g;
open my $fd, "-|",
"$git archive --format=tar --prefix=\'$name\'/ $hash | $command"
"$git archive --format=tar --prefix=\'$name\'/ $hash | $command"
or die_error(undef, "Execute git-tar-tree failed");
binmode STDOUT, ':raw';
print <$fd>;
@@ -3734,7 +3734,7 @@ sub git_commit {
# difftree output is not printed for merges
open my $fd, "-|", git_cmd(), "diff-tree", '-r', "--no-commit-id",
@diff_opts, $parent, $hash, "--"
or die_error(undef, "Open git-diff-tree failed");
or die_error(undef, "Open git-diff-tree failed");
@difftree = map { chomp; $_ } <$fd>;
close $fd or die_error(undef, "Reading git-diff-tree failed");
}
@@ -3934,7 +3934,8 @@ sub git_blobdiff {
# open patch output
open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts,
'-p', $hash_parent_base, $hash_base,
'-p', ($format eq 'html' ? "--full-index" : ()),
$hash_parent_base, $hash_base,
"--", (defined $file_parent ? $file_parent : ()), $file_name
or die_error(undef, "Open git-diff-tree failed");
}
@@ -3969,7 +3970,8 @@ sub git_blobdiff {
}
# open patch output
open $fd, "-|", git_cmd(), "diff", '-p', @diff_opts,
open $fd, "-|", git_cmd(), "diff", @diff_opts,
'-p', ($format eq 'html' ? "--full-index" : ()),
$hash_parent, $hash, "--"
or die_error(undef, "Open git-diff failed");
} else {
@@ -4304,13 +4306,13 @@ sub git_search {
if ($page > 0) {
$paging_nav .=
$cgi->a({-href => href(action=>"search", hash=>$hash,
searchtext=>$searchtext, searchtype=>$searchtype)},
"first");
searchtext=>$searchtext, searchtype=>$searchtype)},
"first");
$paging_nav .= " &sdot; " .
$cgi->a({-href => href(action=>"search", hash=>$hash,
searchtext=>$searchtext, searchtype=>$searchtype,
page=>$page-1),
-accesskey => "p", -title => "Alt-p"}, "prev");
searchtext=>$searchtext, searchtype=>$searchtype,
page=>$page-1),
-accesskey => "p", -title => "Alt-p"}, "prev");
} else {
$paging_nav .= "first";
$paging_nav .= " &sdot; prev";
@@ -4318,9 +4320,9 @@ sub git_search {
if ($#commitlist >= 100) {
$paging_nav .= " &sdot; " .
$cgi->a({-href => href(action=>"search", hash=>$hash,
searchtext=>$searchtext, searchtype=>$searchtype,
page=>$page+1),
-accesskey => "n", -title => "Alt-n"}, "next");
searchtext=>$searchtext, searchtype=>$searchtype,
page=>$page+1),
-accesskey => "n", -title => "Alt-n"}, "next");
} else {
$paging_nav .= " &sdot; next";
}
@@ -4328,9 +4330,9 @@ sub git_search {
if ($#commitlist >= 100) {
$next_link =
$cgi->a({-href => href(action=>"search", hash=>$hash,
searchtext=>$searchtext, searchtype=>$searchtype,
page=>$page+1),
-accesskey => "n", -title => "Alt-n"}, "next");
searchtext=>$searchtext, searchtype=>$searchtype,
page=>$page+1),
-accesskey => "n", -title => "Alt-n"}, "next");
}
git_print_page_nav('','', $hash,$co{'tree'},$hash, $paging_nav);

View File

@@ -198,7 +198,7 @@ static void start_object_request(struct object_request *obj_req)
SHA1_Init(&obj_req->c);
if (prev_posn>0) {
prev_posn = 0;
lseek(obj_req->local, SEEK_SET, 0);
lseek(obj_req->local, 0, SEEK_SET);
ftruncate(obj_req->local, 0);
}
}

View File

@@ -312,7 +312,7 @@ static void start_fetch_loose(struct transfer_request *request)
SHA1_Init(&request->c);
if (prev_posn>0) {
prev_posn = 0;
lseek(request->local_fileno, SEEK_SET, 0);
lseek(request->local_fileno, 0, SEEK_SET);
ftruncate(request->local_fileno, 0);
}
}

View File

@@ -221,7 +221,7 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
struct cache_entry *ce;
ce = make_cache_entry(mode, sha1 ? sha1 : null_sha1, path, stage, refresh);
if (!ce)
return error("cache_addinfo failed: %s", strerror(cache_errno));
return error("addinfo_cache failed for path '%s'", path);
return add_cache_entry(ce, options);
}

View File

@@ -42,13 +42,14 @@ static int verify_packfile(struct packed_git *p,
*/
nr_objects = num_packed_objects(p);
for (i = 0, err = 0; i < nr_objects; i++) {
unsigned char sha1[20];
const unsigned char *sha1;
void *data;
enum object_type type;
unsigned long size;
off_t offset;
if (nth_packed_object_sha1(p, i, sha1))
sha1 = nth_packed_object_sha1(p, i);
if (!sha1)
die("internal error pack-check nth-packed-object");
offset = find_pack_entry_one(sha1, p);
if (!offset)
@@ -82,14 +83,16 @@ static void show_pack_info(struct packed_git *p)
memset(chain_histogram, 0, sizeof(chain_histogram));
for (i = 0; i < nr_objects; i++) {
unsigned char sha1[20], base_sha1[20];
const unsigned char *sha1;
unsigned char base_sha1[20];
const char *type;
unsigned long size;
unsigned long store_size;
off_t offset;
unsigned int delta_chain_length;
if (nth_packed_object_sha1(p, i, sha1))
sha1 = nth_packed_object_sha1(p, i);
if (!sha1)
die("internal error pack-check nth-packed-object");
offset = find_pack_entry_one(sha1, p);
if (!offset)

View File

@@ -24,8 +24,6 @@ unsigned int active_nr, active_alloc, active_cache_changed;
struct cache_tree *active_cache_tree;
int cache_errno;
static void *cache_mmap;
static size_t cache_mmap_size;
@@ -327,7 +325,7 @@ int remove_file_from_cache(const char *path)
return 0;
}
int add_file_to_index(const char *path, int verbose)
int add_file_to_cache(const char *path, int verbose)
{
int size, namelen;
struct stat st;
@@ -643,14 +641,15 @@ int add_cache_entry(struct cache_entry *ce, int option)
* For example, you'd want to do this after doing a "git-read-tree",
* to link up the stat cache details with the proper files.
*/
struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really)
static struct cache_entry *refresh_cache_ent(struct cache_entry *ce, int really, int *err)
{
struct stat st;
struct cache_entry *updated;
int changed, size;
if (lstat(ce->name, &st) < 0) {
cache_errno = errno;
if (err)
*err = errno;
return NULL;
}
@@ -664,7 +663,8 @@ struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really)
}
if (ce_modified(ce, &st, really)) {
cache_errno = EINVAL;
if (err)
*err = EINVAL;
return NULL;
}
@@ -696,6 +696,8 @@ int refresh_cache(unsigned int flags)
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce, *new;
int cache_errno = 0;
ce = active_cache[i];
if (ce_stage(ce)) {
while ((i < active_nr) &&
@@ -709,7 +711,7 @@ int refresh_cache(unsigned int flags)
continue;
}
new = refresh_cache_entry(ce, really);
new = refresh_cache_ent(ce, really, &cache_errno);
if (new == ce)
continue;
if (!new) {
@@ -737,6 +739,11 @@ int refresh_cache(unsigned int flags)
return has_errors;
}
struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really)
{
return refresh_cache_ent(ce, really, NULL);
}
static int verify_hdr(struct cache_header *hdr, unsigned long size)
{
SHA_CTX c;

View File

@@ -1542,15 +1542,14 @@ uint32_t num_packed_objects(const struct packed_git *p)
return (uint32_t)((p->index_size - 20 - 20 - 4*256) / 24);
}
int nth_packed_object_sha1(const struct packed_git *p, uint32_t n,
unsigned char* sha1)
const unsigned char *nth_packed_object_sha1(const struct packed_git *p,
uint32_t n)
{
const unsigned char *index = p->index_data;
index += 4 * 256;
if (num_packed_objects(p) <= n)
return -1;
hashcpy(sha1, index + 24 * n + 4);
return 0;
return NULL;
return index + 24 * n + 4;
}
off_t find_pack_entry_one(const unsigned char *sha1,

View File

@@ -71,7 +71,7 @@ static int match_sha(unsigned len, const unsigned char *a, const unsigned char *
static int find_short_packed_object(int len, const unsigned char *match, unsigned char *sha1)
{
struct packed_git *p;
unsigned char found_sha1[20];
const unsigned char *found_sha1 = NULL;
int found = 0;
prepare_packed_git();
@@ -80,10 +80,10 @@ static int find_short_packed_object(int len, const unsigned char *match, unsigne
uint32_t first = 0, last = num;
while (first < last) {
uint32_t mid = (first + last) / 2;
unsigned char now[20];
const unsigned char *now;
int cmp;
nth_packed_object_sha1(p, mid, now);
now = nth_packed_object_sha1(p, mid);
cmp = hashcmp(match, now);
if (!cmp) {
first = mid;
@@ -96,14 +96,14 @@ static int find_short_packed_object(int len, const unsigned char *match, unsigne
last = mid;
}
if (first < num) {
unsigned char now[20], next[20];
nth_packed_object_sha1(p, first, now);
const unsigned char *now, *next;
now = nth_packed_object_sha1(p, first);
if (match_sha(len, match, now)) {
if (nth_packed_object_sha1(p, first+1, next) ||
!match_sha(len, match, next)) {
next = nth_packed_object_sha1(p, first+1);
if (!next|| !match_sha(len, match, next)) {
/* unique within this pack */
if (!found) {
hashcpy(found_sha1, now);
found_sha1 = now;
found++;
}
else if (hashcmp(found_sha1, now)) {

View File

@@ -83,6 +83,15 @@ test_expect_failure \
git-branch r &&
git-branch -m q r/q'
mv .git/config .git/config-saved
test_expect_success 'git branch -m q Q without config should succeed' '
git-branch -m q Q &&
git-branch -m Q q
'
mv .git/config-saved .git/config
git-config branch.s/s.dummy Hello
test_expect_success \

25
t/t4120-apply-popt.sh Executable file
View File

@@ -0,0 +1,25 @@
#!/bin/sh
#
# Copyright (c) 2007 Shawn O. Pearce
#
test_description='git-apply -p handling.'
. ./test-lib.sh
test_expect_success setup '
mkdir sub &&
echo A >sub/file1 &&
cp sub/file1 file1 &&
git add sub/file1 &&
echo B >sub/file1 &&
git diff >patch.file &&
rm sub/file1 &&
rmdir sub
'
test_expect_success 'apply git diff with -p2' '
git apply -p2 patch.file
'
test_done

View File

@@ -35,7 +35,8 @@ git commit -q -a -m first
git checkout -b second master
git show first:a1 |
sed -e 's/To die, t/To die! T/' -e 's/life;$/life./' > a1
sed -e 's/To die, t/To die! T/' > a1
echo "* END *" >>a1
git commit -q -a -m second
# activate rerere
@@ -50,10 +51,10 @@ test_expect_success 'recorded preimage' "grep ======= $rr/preimage"
test_expect_success 'no postimage or thisimage yet' \
"test ! -f $rr/postimage -a ! -f $rr/thisimage"
test_expect_success 'preimage have right number of lines' '
test_expect_success 'preimage has right number of lines' '
cnt=$(sed -ne "/^<<<<<<</,/^>>>>>>>/p" $rr/preimage | wc -l) &&
test "$cnt" = 10
test $cnt = 9
'
@@ -75,10 +76,10 @@ cat > expect << EOF
For in that sleep of death what dreams may come
When we have shuffled off this mortal coil,
Must give us pause: there's the respect
-<<<<<<<
-That makes calamity of so long life.
-=======
That makes calamity of so long life;
-<<<<<<<
-=======
-* END *
->>>>>>>
EOF
git rerere diff > out

View File

@@ -137,4 +137,8 @@ test_expect_success \
'validate file contents with prefix' \
'diff -r a e/prefix/a'
test_expect_success \
'git-archive --list outside of a git repo' \
'GIT_DIR=some/non-existing/directory git-archive --list'
test_done

View File

@@ -163,7 +163,7 @@ test_sequence()
# the bisection point is the head - this is the bad point.
#
test_output_expect_success "--bisect l5 ^root" 'git-rev-list $_bisect_option l5 ^root' <<EOF
test_output_expect_success "$_bisect_option l5 ^root" 'git-rev-list $_bisect_option l5 ^root' <<EOF
c3
EOF

View File

@@ -7,7 +7,8 @@ test_description='git-rev-list trivial path optimization test'
test_expect_success setup '
echo Hello > a &&
git add a &&
git commit -m "Initial commit" a
git commit -m "Initial commit" a &&
initial=$(git rev-parse --verify HEAD)
'
test_expect_success path-optimization '
@@ -16,4 +17,35 @@ test_expect_success path-optimization '
test $(git-rev-list $commit -- . | wc -l) = 1
'
test_expect_success 'further setup' '
git checkout -b side &&
echo Irrelevant >c &&
git add c &&
git commit -m "Side makes an irrelevant commit" &&
echo "More Irrelevancy" >c &&
git add c &&
git commit -m "Side makes another irrelevant commit" &&
echo Bye >a &&
git add a &&
git commit -m "Side touches a" &&
side=$(git rev-parse --verify HEAD) &&
echo "Yet more Irrelevancy" >c &&
git add c &&
git commit -m "Side makes yet another irrelevant commit" &&
git checkout master &&
echo Another >b &&
git add b &&
git commit -m "Master touches b" &&
git merge side &&
echo Touched >b &&
git add b &&
git commit -m "Master touches b again"
'
test_expect_success 'path optimization 2' '
( echo "$side"; echo "$initial" ) >expected &&
git rev-list HEAD -- a >actual &&
diff -u expected actual
'
test_done

View File

@@ -260,7 +260,7 @@ static void wt_status_print_untracked(struct wt_status *s)
if (file_exists(x))
add_excludes_from_file(&dir, x);
read_directory(&dir, ".", "", 0);
read_directory(&dir, ".", "", 0, NULL);
for(i = 0; i < dir.nr; i++) {
/* check for matching entry, which is unmerged; lifted from
* builtin-ls-files:show_other_files */