Merge branch 'master' of git://repo.or.cz/alt-git

This commit is contained in:
Johannes Sixt
2008-12-09 08:11:17 +01:00
56 changed files with 817 additions and 195 deletions

1
.gitignore vendored
View File

@@ -118,6 +118,7 @@ git-show
git-show-branch
git-show-index
git-show-ref
git-stage
git-stash
git-status
git-stripspace

View File

@@ -4,40 +4,53 @@ GIT v1.6.0.5 Release Notes
Fixes since v1.6.0.4
--------------------
* 'git checkout' used to crash when your HEAD was pointing at a deleted
* "git checkout" used to crash when your HEAD was pointing at a deleted
branch.
* 'git checkout' from an un-checked-out state did not allow switching out
* "git checkout" from an un-checked-out state did not allow switching out
of the current branch.
* 'git diff' always allowed GIT_EXTERNAL_DIFF and --no-ext-diff was no-op for
* "git diff" always allowed GIT_EXTERNAL_DIFF and --no-ext-diff was no-op for
the command.
* 'git fast-export' did not export all tags.
* Giving 3 or more tree-ish to "git diff" is supposed to show the combined
diff from second and subsequent trees to the first one, but the order was
screwed up.
* 'git ls-files --with-tree=<tree>' did not work with options other
* "git fast-export" did not export all tags.
* "git ls-files --with-tree=<tree>" did not work with options other
than -c, most notably with -m.
* 'git pack-objects' did not make its best effort to honor --max-pack-size
* "git pack-objects" did not make its best effort to honor --max-pack-size
option when a single first object already busted the given limit and
placed many objects in a single pack.
* 'git-p4' fast import frontend was too eager to trigger its keyword expansion
* "git-p4" fast import frontend was too eager to trigger its keyword expansion
logic, even on a keyword-looking string that does not have closing '$' on the
same line.
* 'git push $there' when the remote $there is defined in $GIT_DIR/branches/$there
* "git push $there" when the remote $there is defined in $GIT_DIR/branches/$there
behaves more like what cg-push from Cogito used to work.
* 'git tag' did not complain when given mutually incompatible set of options.
* when giving up resolving a conflicted merge, "git reset --hard" failed
to remove new paths from the working tree.
* 'make check' cannot be run without sparse; people may have meant to say
'make test' instead, so suggest that.
* "git tag" did not complain when given mutually incompatible set of options.
* The message constructed in the internal editor was discarded when "git
tag -s" failed to sign the message, which was often caused by the user
not configuring GPG correctly.
* "make check" cannot be run without sparse; people may have meant to say
"make test" instead, so suggest that.
* Internal diff machinery had a corner case performance bug that choked on
a large file with many repeated contents.
* "git repack" used to grab objects out of packs marked with .keep
into a new pack.
* Many unsafe call to sprintf() style varargs functions are corrected.
* Also contains quite a few documentation updates.
--
O=v1.6.0.4-39-g27f6496

View File

@@ -69,12 +69,18 @@ on.
* "git add -N path..." adds the named paths as an empty blob, so that
subsequent "git diff" will show a diff as if they are creation events.
* "git add" gained a built-in synonym for people who want to say "stage
changes" instead of "add contents to the staging area" which amounts
to the same thing.
* "git apply" learned --include=paths option, similar to the existing
--exclude=paths option.
* "git bisect" is careful about a user mistake and suggests testing of
merge base first when good is not a strict ancestor of bad.
* "git bisect skip" can take a range of commits.
* "git blame" re-encodes the commit metainfo to UTF-8 from i18n.commitEncoding
by default.
@@ -129,16 +135,10 @@ on.
cannot produce a patch that can be applied, so this is disabled in
format-patch among other things).
* "git diff" hunk header pattern for ObjC has been added.
* "--cached" option to "git diff has an easier to remember synonym "--staged",
to ask "what is the difference between the given commit and the
contents staged in the index?"
* a "textconv" filter that makes binary files textual form for human
consumption can be specified as an attribute for paths; "git diff"
learnt to make use of it.
* "git for-each-ref" learned "refname:short" token that gives an
unambiguously abbreviated refname.
@@ -191,9 +191,6 @@ on.
* "git remote show $remote" lists remote branches one-per-line now.
* when giving up resolving a conflicted merge, "git reset --hard" failed
to remove new paths from the working tree. [cherry-pick to 'maint'?]
* "git send-email" can be given revision range instead of files and
maildirs on the command line, and automatically runs format-patch to
generate patches for the given revision range.
@@ -238,19 +235,18 @@ release, unless otherwise noted.
it (we still need to fix a similar nonsense when S is a submodule and F
is a path in it).
* "git am" after stopping at a broken patch lost --whitespace, -C, -p and
--3way options given from the command line initially.
* "git diff --stdin" used to take two trees on a line and compared them,
but we dropped support for such a use case long time ago. This has
been resurrected.
* Giving 3 or more tree-ish to "git diff" is supposed to show the combined
diff from second and subsequent trees to the first one. b75271d ("git
diff <tree>{3,}": do not reverse order of arguments, 2008-10-10) needs
to be cherry-picked to 'maint'.
* "git filter-branch" failed to rewrite a tag name with slashes in it.
* "git repack" used to grab objects out of packs marked with .keep
into a new pack (fix scheduled to be further downmerged to maint).
* "git rm --cached" used to allow an empty blob that was added earlier to
be removed without --force, even when the file in the work tree has
since been modified.
* "git push --tags --all $there" failed with generic usage message without
telling saying these two options are incompatible.
@@ -259,12 +255,11 @@ release, unless otherwise noted.
timestamp part, exposing internal implementation detail. Also these did
not work with --fixed-strings match at all.
* Internal diff machinery had a corner case performance bug that choked on a
large file with many repeated contents (fix scheduled to be further cherry-
picked to maint).
* "gitweb" did not mark non-ASCII characters imported from external HTML fragments
correctly.
--
exec >/var/tmp/1
O=v1.6.0.4-854-gaaab7ea
O=v1.6.1-rc1-55-gd8af75d
echo O=$(git describe master)
git shortlog --no-merges $O..master ^maint

View File

@@ -19,7 +19,7 @@ on the subcommand:
git bisect start [<bad> [<good>...]] [--] [<paths>...]
git bisect bad [<rev>]
git bisect good [<rev>...]
git bisect skip [<rev>...]
git bisect skip [(<rev>|<range>)...]
git bisect reset [<branch>]
git bisect visualize
git bisect replay <logfile>
@@ -164,6 +164,25 @@ But computing the commit to test may be slower afterwards and git may
eventually not be able to tell the first bad among a bad and one or
more "skip"ped commits.
You can even skip a range of commits, instead of just one commit,
using the "'<commit1>'..'<commit2>'" notation. For example:
------------
$ git bisect skip v2.5..v2.6
------------
would mean that no commit between `v2.5` excluded and `v2.6` included
can be tested.
Note that if you want to also skip the first commit of a range you can
use something like:
------------
$ git bisect skip v2.5 v2.5..v2.6
------------
and the commit pointed to by `v2.5` will be skipped too.
Cutting down bisection by giving more parameters to bisect start
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -0,0 +1,19 @@
git-stage(1)
==============
NAME
----
git-stage - Add file contents to the staging area
SYNOPSIS
--------
[verse]
'git stage' args...
DESCRIPTION
-----------
This is a synonym for linkgit:git-add[1]. Please refer to the
documentation of that command.

View File

@@ -43,9 +43,10 @@ unreleased) version of git, that is available from 'master'
branch of the `git.git` repository.
Documentation for older releases are available here:
* link:v1.6.0.4/git.html[documentation for release 1.6.0.4]
* link:v1.6.0.5/git.html[documentation for release 1.6.0.5]
* release notes for
link:RelNotes-1.6.0.5.txt[1.6.0.5],
link:RelNotes-1.6.0.4.txt[1.6.0.4],
link:RelNotes-1.6.0.3.txt[1.6.0.3],
link:RelNotes-1.6.0.2.txt[1.6.0.2],

View File

@@ -4572,4 +4572,3 @@ Alternates, clone -reference, etc.
More on recovery from repository corruption. See:
http://marc.theaimsgroup.com/?l=git&m=117263864820799&w=2
http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2
http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2

View File

@@ -90,6 +90,8 @@ all::
#
# Define NO_MMAP if you want to avoid mmap.
#
# Define NO_PTHREADS if you do not have or do not want to use Pthreads.
#
# Define NO_PREAD if you have a problem with pread() system call (e.g.
# cygwin.dll before v1.5.22).
#
@@ -164,6 +166,7 @@ uname_M := $(shell sh -c 'uname -m 2>/dev/null || echo not')
uname_O := $(shell sh -c 'uname -o 2>/dev/null || echo not')
uname_R := $(shell sh -c 'uname -r 2>/dev/null || echo not')
uname_P := $(shell sh -c 'uname -p 2>/dev/null || echo not')
uname_V := $(shell sh -c 'uname -v 2>/dev/null || echo not')
# CFLAGS and LDFLAGS are for the users to override from the command line.
@@ -317,6 +320,7 @@ BUILT_INS += git-merge-subtree$X
BUILT_INS += git-peek-remote$X
BUILT_INS += git-repo-config$X
BUILT_INS += git-show$X
BUILT_INS += git-stage$X
BUILT_INS += git-status$X
BUILT_INS += git-whatchanged$X
@@ -722,6 +726,11 @@ ifeq ($(uname_S),AIX)
INTERNAL_QSORT = UnfortunatelyYes
NEEDS_LIBICONV=YesPlease
BASIC_CFLAGS += -D_LARGE_FILES
ifneq ($(shell expr "$(uname_V)" : '[1234]'),1)
THREADED_DELTA_SEARCH = YesPlease
else
NO_PTHREADS = YesPlease
endif
endif
ifeq ($(uname_S),GNU)
# GNU/Hurd
@@ -766,6 +775,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))
NO_STRCASESTR = YesPlease
NO_STRLCPY = YesPlease
NO_MEMMEM = YesPlease
NO_PTHREADS = YesPlease
NEEDS_LIBICONV = YesPlease
OLD_ICONV = YesPlease
NO_C99_FORMAT = YesPlease
@@ -1017,9 +1027,15 @@ ifdef INTERNAL_QSORT
COMPAT_OBJS += compat/qsort.o
endif
ifdef NO_PTHREADS
THREADED_DELTA_SEARCH =
BASIC_CFLAGS += -DNO_PTHREADS
else
EXTLIBS += $(PTHREAD_LIBS)
endif
ifdef THREADED_DELTA_SEARCH
BASIC_CFLAGS += -DTHREADED_DELTA_SEARCH
EXTLIBS += $(PTHREAD_LIBS)
LIB_OBJS += thread-utils.o
endif
ifdef DIR_HAS_BSD_GROUP_SEMANTICS

View File

@@ -639,7 +639,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
active_cache_tree = cache_tree();
if (cache_tree_update(active_cache_tree,
active_cache, active_nr, 0, 0) < 0) {
error("Error building trees; the index is unmerged?");
error("Error building trees");
return 0;
}

View File

@@ -780,7 +780,8 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
struct ref *ref_cpy;
fetch_pack_setup();
memcpy(&args, my_args, sizeof(args));
if (&args != my_args)
memcpy(&args, my_args, sizeof(args));
if (args.depth > 0) {
if (stat(git_path("shallow"), &st))
st.st_mtime = 0;

View File

@@ -201,12 +201,16 @@ static void check_unreachable_object(struct object *obj)
char *buf = read_sha1_file(obj->sha1,
&type, &size);
if (buf) {
fwrite(buf, size, 1, f);
if (fwrite(buf, size, 1, f) != 1)
die("Could not write %s: %s",
filename, strerror(errno));
free(buf);
}
} else
fprintf(f, "%s\n", sha1_to_hex(obj->sha1));
fclose(f);
if (fclose(f))
die("Could not finish %s: %s",
filename, strerror(errno));
}
return;
}

View File

@@ -293,8 +293,10 @@ static void squash_message(void)
pretty_print_commit(rev.commit_format, commit, &out, rev.abbrev,
NULL, NULL, rev.date_mode, 0);
}
write(fd, out.buf, out.len);
close(fd);
if (write(fd, out.buf, out.len) < 0)
die("Writing SQUASH_MSG: %s", strerror(errno));
if (close(fd))
die("Finishing SQUASH_MSG: %s", strerror(errno));
strbuf_release(&out);
}

View File

@@ -31,7 +31,8 @@ static void add_list(const char *name)
static int check_local_mod(unsigned char *head, int index_only)
{
/* items in list are already sorted in the cache order,
/*
* Items in list are already sorted in the cache order,
* so we could do this a lot more efficiently by using
* tree_desc based traversal if we wanted to, but I am
* lazy, and who cares if removal of files is a tad
@@ -71,25 +72,55 @@ static int check_local_mod(unsigned char *head, int index_only)
*/
continue;
}
/*
* "rm" of a path that has changes need to be treated
* carefully not to allow losing local changes
* accidentally. A local change could be (1) file in
* work tree is different since the index; and/or (2)
* the user staged a content that is different from
* the current commit in the index.
*
* In such a case, you would need to --force the
* removal. However, "rm --cached" (remove only from
* the index) is safe if the index matches the file in
* the work tree or the HEAD commit, as it means that
* the content being removed is available elsewhere.
*/
/*
* Is the index different from the file in the work tree?
*/
if (ce_match_stat(ce, &st, 0))
local_changes = 1;
/*
* Is the index different from the HEAD commit? By
* definition, before the very initial commit,
* anything staged in the index is treated by the same
* way as changed from the HEAD.
*/
if (no_head
|| get_tree_entry(head, name, sha1, &mode)
|| ce->ce_mode != create_ce_mode(mode)
|| hashcmp(ce->sha1, sha1))
staged_changes = 1;
if (local_changes && staged_changes &&
!(index_only && is_empty_blob_sha1(ce->sha1)))
errs = error("'%s' has staged content different "
"from both the file and the HEAD\n"
"(use -f to force removal)", name);
/*
* If the index does not match the file in the work
* tree and if it does not match the HEAD commit
* either, (1) "git rm" without --cached definitely
* will lose information; (2) "git rm --cached" will
* lose information unless it is about removing an
* "intent to add" entry.
*/
if (local_changes && staged_changes) {
if (!index_only || !(ce->ce_flags & CE_INTENT_TO_ADD))
errs = error("'%s' has staged content different "
"from both the file and the HEAD\n"
"(use -f to force removal)", name);
}
else if (!index_only) {
/* It's not dangerous to "git rm --cached" a
* file if the index matches the file or the
* HEAD, since it means the deleted content is
* still available somewhere.
*/
if (staged_changes)
errs = error("'%s' has changes staged in the index\n"
"(use --cached to keep the file, "

View File

@@ -253,6 +253,15 @@ static void write_tag_body(int fd, const unsigned char *sha1)
free(buf);
}
static int build_tag_object(struct strbuf *buf, int sign, unsigned char *result)
{
if (sign && do_sign(buf) < 0)
return error("unable to sign the tag");
if (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0)
return error("unable to write tag file");
return 0;
}
static void create_tag(const unsigned char *object, const char *tag,
struct strbuf *buf, int message, int sign,
unsigned char *prev, unsigned char *result)
@@ -260,6 +269,7 @@ static void create_tag(const unsigned char *object, const char *tag,
enum object_type type;
char header_buf[1024];
int header_len;
char *path = NULL;
type = sha1_object_info(object, NULL);
if (type <= OBJ_NONE)
@@ -279,7 +289,6 @@ static void create_tag(const unsigned char *object, const char *tag,
die("tag header too big.");
if (!message) {
char *path;
int fd;
/* write the template message before editing: */
@@ -300,9 +309,6 @@ static void create_tag(const unsigned char *object, const char *tag,
"Please supply the message using either -m or -F option.\n");
exit(1);
}
unlink(path);
free(path);
}
stripspace(buf, 1);
@@ -312,10 +318,16 @@ static void create_tag(const unsigned char *object, const char *tag,
strbuf_insert(buf, 0, header_buf, header_len);
if (sign && do_sign(buf) < 0)
die("unable to sign the tag");
if (write_sha1_file(buf->buf, buf->len, tag_type, result) < 0)
die("unable to write tag file");
if (build_tag_object(buf, sign, result) < 0) {
if (path)
fprintf(stderr, "The tag message has been left in %s\n",
path);
exit(128);
}
if (path) {
unlink(path);
free(path);
}
}
struct msg_arg {

View File

@@ -42,7 +42,7 @@ int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
die("%s: error reading the index", me);
break;
case WRITE_TREE_UNMERGED_INDEX:
die("%s: error building trees; the index is unmerged?", me);
die("%s: error building trees", me);
break;
case WRITE_TREE_PREFIX_ERROR:
die("%s: prefix %s not found", me, prefix);

View File

@@ -155,13 +155,17 @@ static int verify_cache(struct cache_entry **cache,
funny = 0;
for (i = 0; i < entries; i++) {
struct cache_entry *ce = cache[i];
if (ce_stage(ce)) {
if (ce_stage(ce) || (ce->ce_flags & CE_INTENT_TO_ADD)) {
if (10 < ++funny) {
fprintf(stderr, "...\n");
break;
}
fprintf(stderr, "%s: unmerged (%s)\n",
ce->name, sha1_to_hex(ce->sha1));
if (ce_stage(ce))
fprintf(stderr, "%s: unmerged (%s)\n",
ce->name, sha1_to_hex(ce->sha1));
else
fprintf(stderr, "%s: not added yet\n",
ce->name);
}
}
if (funny)

59
cache.h
View File

@@ -115,6 +115,26 @@ struct ondisk_cache_entry {
char name[FLEX_ARRAY]; /* more */
};
/*
* This struct is used when CE_EXTENDED bit is 1
* The struct must match ondisk_cache_entry exactly from
* ctime till flags
*/
struct ondisk_cache_entry_extended {
struct cache_time ctime;
struct cache_time mtime;
unsigned int dev;
unsigned int ino;
unsigned int mode;
unsigned int uid;
unsigned int gid;
unsigned int size;
unsigned char sha1[20];
unsigned short flags;
unsigned short flags2;
char name[FLEX_ARRAY]; /* more */
};
struct cache_entry {
unsigned int ce_ctime;
unsigned int ce_mtime;
@@ -136,7 +156,15 @@ struct cache_entry {
#define CE_VALID (0x8000)
#define CE_STAGESHIFT 12
/* In-memory only */
/*
* Range 0xFFFF0000 in ce_flags is divided into
* two parts: in-memory flags and on-disk ones.
* Flags in CE_EXTENDED_FLAGS will get saved on-disk
* if you want to save a new flag, add it in
* CE_EXTENDED_FLAGS
*
* In-memory only flags
*/
#define CE_UPDATE (0x10000)
#define CE_REMOVE (0x20000)
#define CE_UPTODATE (0x40000)
@@ -145,6 +173,25 @@ struct cache_entry {
#define CE_HASHED (0x100000)
#define CE_UNHASHED (0x200000)
/*
* Extended on-disk flags
*/
#define CE_INTENT_TO_ADD 0x20000000
/* CE_EXTENDED2 is for future extension */
#define CE_EXTENDED2 0x80000000
#define CE_EXTENDED_FLAGS (CE_INTENT_TO_ADD)
/*
* Safeguard to avoid saving wrong flags:
* - CE_EXTENDED2 won't get saved until its semantic is known
* - Bits in 0x0000FFFF have been saved in ce_flags already
* - Bits in 0x003F0000 are currently in-memory flags
*/
#if CE_EXTENDED_FLAGS & 0x803FFFFF
#error "CE_EXTENDED_FLAGS out of range"
#endif
/*
* Copy the sha1 and stat state of a cache entry from one to
* another. But we never change the name, or the hash state!
@@ -177,7 +224,9 @@ static inline size_t ce_namelen(const struct cache_entry *ce)
}
#define ce_size(ce) cache_entry_size(ce_namelen(ce))
#define ondisk_ce_size(ce) ondisk_cache_entry_size(ce_namelen(ce))
#define ondisk_ce_size(ce) (((ce)->ce_flags & CE_EXTENDED) ? \
ondisk_cache_entry_extended_size(ce_namelen(ce)) : \
ondisk_cache_entry_size(ce_namelen(ce)))
#define ce_stage(ce) ((CE_STAGEMASK & (ce)->ce_flags) >> CE_STAGESHIFT)
#define ce_uptodate(ce) ((ce)->ce_flags & CE_UPTODATE)
#define ce_mark_uptodate(ce) ((ce)->ce_flags |= CE_UPTODATE)
@@ -220,8 +269,10 @@ static inline int ce_to_dtype(const struct cache_entry *ce)
(S_ISREG(mode) ? (S_IFREG | ce_permissions(mode)) : \
S_ISLNK(mode) ? S_IFLNK : S_ISDIR(mode) ? S_IFDIR : S_IFGITLINK)
#define cache_entry_size(len) ((offsetof(struct cache_entry,name) + (len) + 8) & ~7)
#define ondisk_cache_entry_size(len) ((offsetof(struct ondisk_cache_entry,name) + (len) + 8) & ~7)
#define flexible_size(STRUCT,len) ((offsetof(struct STRUCT,name) + (len) + 8) & ~7)
#define cache_entry_size(len) flexible_size(cache_entry,len)
#define ondisk_cache_entry_size(len) flexible_size(ondisk_cache_entry,len)
#define ondisk_cache_entry_extended_size(len) flexible_size(ondisk_cache_entry_extended,len)
struct index_state {
struct cache_entry **cache;

View File

@@ -51,4 +51,5 @@ OLD_ICONV=@OLD_ICONV@
NO_DEFLATE_BOUND=@NO_DEFLATE_BOUND@
FREAD_READS_DIRECTORIES=@FREAD_READS_DIRECTORIES@
SNPRINTF_RETURNS_BOGUS=@SNPRINTF_RETURNS_BOGUS@
NO_PTHREADS=@NO_PTHREADS@
PTHREAD_LIBS=@PTHREAD_LIBS@

View File

@@ -490,6 +490,8 @@ AC_SUBST(NO_MKDTEMP)
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
# Enable it on Windows. By default, symrefs are still used.
#
# Define NO_PTHREADS if we do not have pthreads
#
# Define PTHREAD_LIBS to the linker flag used for Pthread support.
AC_LANG_CONFTEST([AC_LANG_PROGRAM(
[[#include <pthread.h>]],
@@ -502,9 +504,12 @@ else
${CC} -lpthread conftest.c -o conftest.o > /dev/null 2>&1
if test $? -eq 0;then
PTHREAD_LIBS="-lpthread"
else
NO_PTHREADS=UnfortunatelyYes
fi
fi
AC_SUBST(PTHREAD_LIBS)
AC_SUBST(NO_PTHREADS)
## Site configuration (override autodetection)
## --with-PACKAGE[=ARG] and --without-PACKAGE

View File

@@ -245,7 +245,15 @@ def p4Cmd(cmd):
def p4Where(depotPath):
if not depotPath.endswith("/"):
depotPath += "/"
output = p4Cmd("where %s..." % depotPath)
depotPath = depotPath + "..."
outputList = p4CmdList("where %s" % depotPath)
output = None
for entry in outputList:
if entry["depotFile"] == depotPath:
output = entry
break
if output == None:
return ""
if output["code"] == "error":
return ""
clientPath = ""

View File

@@ -247,10 +247,11 @@ else
exit 1
}
# -s, -u, -k and --whitespace flags are kept for the
# resuming session after a patch failure.
# -3 and -i can and must be given when resuming.
echo " $ws" >"$dotest/whitespace"
# -s, -u, -k, --whitespace, -3, -C and -p flags are kept
# for the resuming session after a patch failure.
# -i can and must be given when resuming.
echo " $git_apply_opt" >"$dotest/apply-opt"
echo "$threeway" >"$dotest/threeway"
echo "$sign" >"$dotest/sign"
echo "$utf8" >"$dotest/utf8"
echo "$keep" >"$dotest/keep"
@@ -283,7 +284,11 @@ if test "$(cat "$dotest/keep")" = t
then
keep=-k
fi
ws=`cat "$dotest/whitespace"`
if test "$(cat "$dotest/threeway")" = t
then
threeway=t
fi
git_apply_opt=$(cat "$dotest/apply-opt")
if test "$(cat "$dotest/sign")" = t
then
SIGNOFF=`git var GIT_COMMITTER_IDENT | sed -e '

View File

@@ -9,7 +9,7 @@ git bisect bad [<rev>]
mark <rev> a known-bad revision.
git bisect good [<rev>...]
mark <rev>... known-good revisions.
git bisect skip [<rev>...]
git bisect skip [(<rev>|<range>)...]
mark <rev>... untestable revisions.
git bisect next
find next bisection to test and check it out.
@@ -199,11 +199,11 @@ bisect_skip() {
*..*)
revs=$(git rev-list "$arg") || die "Bad rev input: $arg" ;;
*)
revs="'$arg'" ;;
revs=$(sq "$arg") ;;
esac
all="$all $revs"
done
bisect_state 'skip' $all
eval bisect_state 'skip' $all
}
bisect_state() {

View File

@@ -256,7 +256,7 @@ while read commit parents; do
*)
# The commit may not have the subdirectory at all
err=$(git read-tree -i -m $commit:"$filter_subdir" 2>&1) || {
if ! git rev-parse --verify $commit:"$filter_subdir" 2>/dev/null
if ! git rev-parse -q --verify $commit:"$filter_subdir"
then
rm -f "$GIT_INDEX_FILE"
else

View File

@@ -33,10 +33,15 @@ proc push_to {remote} {
proc start_push_anywhere_action {w} {
global push_urltype push_remote push_url push_thin push_tags
global push_force
global repo_config
set is_mirror 0
set r_url {}
switch -- $push_urltype {
remote {set r_url $push_remote}
remote {
set r_url $push_remote
catch {set is_mirror $repo_config(remote.$push_remote.mirror)}
}
url {set r_url $push_url}
}
if {$r_url eq {}} return
@@ -53,23 +58,29 @@ proc start_push_anywhere_action {w} {
lappend cmd --tags
}
lappend cmd $r_url
set cnt 0
foreach i [$w.source.l curselection] {
set b [$w.source.l get $i]
lappend cmd "refs/heads/$b:refs/heads/$b"
incr cnt
}
if {$cnt == 0} {
return
} elseif {$cnt == 1} {
set unit branch
if {$is_mirror} {
set cons [console::new \
[mc "push %s" $r_url] \
[mc "Mirroring to %s" $r_url]]
} else {
set unit branches
}
set cnt 0
foreach i [$w.source.l curselection] {
set b [$w.source.l get $i]
lappend cmd "refs/heads/$b:refs/heads/$b"
incr cnt
}
if {$cnt == 0} {
return
} elseif {$cnt == 1} {
set unit branch
} else {
set unit branches
}
set cons [console::new \
[mc "push %s" $r_url] \
[mc "Pushing %s %s to %s" $cnt $unit $r_url]]
set cons [console::new \
[mc "push %s" $r_url] \
[mc "Pushing %s %s to %s" $cnt $unit $r_url]]
}
console::exec $cons $cmd
destroy $w
}

View File

@@ -20,7 +20,7 @@ while read dangling type sha1
do
case "$dangling" in
dangling)
if git rev-parse --verify "$sha1^0" >/dev/null 2>/dev/null
if git rev-parse -q --verify "$sha1^0" >/dev/null
then
dir="$laf/commit"
git show-branch "$sha1"

View File

@@ -121,13 +121,13 @@ test true = "$rebase" && {
test -z "$origin" && origin=$(get_default_remote)
reflist="$(get_remote_refs_for_fetch "$@" 2>/dev/null |
sed "s|refs/heads/\(.*\):|\1|")" &&
oldremoteref="$(git rev-parse --verify \
"refs/remotes/$origin/$reflist" 2>/dev/null)"
oldremoteref="$(git rev-parse -q --verify \
"refs/remotes/$origin/$reflist")"
}
orig_head=$(git rev-parse --verify HEAD 2>/dev/null)
orig_head=$(git rev-parse -q --verify HEAD)
git fetch $verbosity --update-head-ok "$@" || exit 1
curr_head=$(git rev-parse --verify HEAD 2>/dev/null)
curr_head=$(git rev-parse -q --verify HEAD)
if test -n "$orig_head" && test "$curr_head" != "$orig_head"
then
# The fetch involved updating the current branch.

View File

@@ -365,10 +365,10 @@ case "$#" in
switch_to="$2"
if git show-ref --verify --quiet -- "refs/heads/$2" &&
branch=$(git rev-parse --verify "refs/heads/$2" 2>/dev/null)
branch=$(git rev-parse -q --verify "refs/heads/$2")
then
head_name="refs/heads/$2"
elif branch=$(git rev-parse --verify "$2" 2>/dev/null)
elif branch=$(git rev-parse -q --verify "$2")
then
head_name="detached HEAD"
else

View File

@@ -413,7 +413,7 @@ cmd_summary() {
test $summary_limit = 0 && return
if rev=$(git rev-parse --verify "$1^0" 2>/dev/null)
if rev=$(git rev-parse -q --verify "$1^0")
then
head=$rev
shift
@@ -464,11 +464,11 @@ cmd_summary() {
missing_dst=
test $mod_src = 160000 &&
! GIT_DIR="$name/.git" git-rev-parse --verify $sha1_src^0 >/dev/null 2>&1 &&
! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_src^0 >/dev/null &&
missing_src=t
test $mod_dst = 160000 &&
! GIT_DIR="$name/.git" git-rev-parse --verify $sha1_dst^0 >/dev/null 2>&1 &&
! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
missing_dst=t
total_commits=

View File

@@ -558,7 +558,7 @@ sub cmd_branch {
my ($src, $rev, undef, $gs) = working_head_info($head);
my $remote = Git::SVN::read_all_remotes()->{svn};
my $remote = Git::SVN::read_all_remotes()->{$gs->{repo_id}};
my $glob = $remote->{ $_tag ? 'tags' : 'branches' };
my ($lft, $rgt) = @{ $glob->{path} }{qw/left right/};
my $dst = join '/', $remote->{url}, $lft, $branch_name, ($rgt || ());

5
git.c
View File

@@ -195,8 +195,8 @@ static int handle_alias(int *argcp, const char ***argv)
ret = 1;
}
if (subdir)
chdir(subdir);
if (subdir && chdir(subdir))
die("Cannot change to %s: %s", subdir, strerror(errno));
errno = saved_errno;
@@ -266,6 +266,7 @@ static void handle_internal_command(int argc, const char **argv)
const char *cmd = argv[0];
static struct cmd_struct commands[] = {
{ "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
{ "stage", cmd_add, RUN_SETUP | NEED_WORK_TREE },
{ "annotate", cmd_annotate, RUN_SETUP },
{ "apply", cmd_apply },
{ "archive", cmd_archive },

View File

@@ -199,11 +199,7 @@ proc parseviewargs {n arglist} {
set nextisval 1
lappend glflags $arg
}
"--not" {
set notflag [expr {!$notflag}]
lappend revargs $arg
}
"--all" {
"--not" - "--all" {
lappend revargs $arg
}
"--merge" {
@@ -1915,6 +1911,9 @@ proc makewindow {} {
{mc "Reload" command reloadcommits -accelerator Meta1-F5}
{mc "Reread references" command rereadrefs}
{mc "List references" command showrefs -accelerator F2}
{xx "" separator}
{mc "Start git gui" command {exec git gui &}}
{xx "" separator}
{mc "Quit" command doquit -accelerator Meta1-Q}
}}
{mc "Edit" cascade {
@@ -3407,6 +3406,7 @@ proc show_line_source {} {
error_popup [mc "Couldn't start git blame: %s" $err]
return
}
nowbusy blaming [mc "Searching"]
fconfigure $f -blocking 0
set i [reg_instance $f]
set blamestuff($i) {}
@@ -3420,6 +3420,7 @@ proc stopblaming {} {
if {[info exists blameinst]} {
stop_instance $blameinst
unset blameinst
notbusy blaming
}
}
@@ -3434,6 +3435,7 @@ proc read_line_source {fd inst} {
}
unset commfd($inst)
unset blameinst
notbusy blaming
fconfigure $fd -blocking 1
if {[catch {close $fd} err]} {
error_popup [mc "Error running git blame: %s" $err]
@@ -4122,7 +4124,7 @@ proc askvhighlight {row id} {
proc hfiles_change {} {
global highlight_files filehighlight fhighlights fh_serial
global highlight_paths gdttype
global highlight_paths
if {[info exists filehighlight]} {
# delete previous highlights
@@ -6287,10 +6289,11 @@ proc findmore {} {
proc findselectline {l} {
global findloc commentend ctext findcurline markingmatches gdttype
set markingmatches 1
set markingmatches [expr {$gdttype eq [mc "containing:"]}]
set findcurline $l
selectline $l 1
if {$findloc == [mc "All fields"] || $findloc == [mc "Comments"]} {
if {$markingmatches &&
($findloc eq [mc "All fields"] || $findloc eq [mc "Comments"])} {
# highlight the matches in the comments
set f [$ctext get 1.0 $commentend]
set matches [findmatches $f]
@@ -7130,7 +7133,7 @@ proc gettreediffline {gdtf ids} {
set treediffs($ids) $treediff
}
unset treepending
if {$cmitmode eq "tree"} {
if {$cmitmode eq "tree" && [llength $diffids] == 1} {
gettree $diffids
} elseif {$ids != $diffids} {
if {![info exists diffmergeid]} {

View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: git-gui\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2008-10-18 22:03+1100\n"
"PO-Revision-Date: 2008-05-24 22:40+0200\n"
"POT-Creation-Date: 2008-10-25 13:18+0200\n"
"PO-Revision-Date: 2008-10-25 13:23+0200\n"
"Last-Translator: Christian Stimming <stimming@tuhh.de>\n"
"Language-Team: German\n"
"MIME-Version: 1.0\n"
@@ -19,6 +19,14 @@ msgstr ""
msgid "Couldn't get list of unmerged files:"
msgstr "Liste der nicht-zusammengeführten Dateien nicht gefunden:"
#: gitk:272
msgid "Error parsing revisions:"
msgstr "Fehler beim Laden der Versionen:"
#: gitk:327
msgid "Error executing --argscmd command:"
msgstr "Fehler beim --argscmd Kommando:"
#: gitk:340
msgid "No files selected: --merge specified but no files are unmerged."
msgstr ""
@@ -283,9 +291,9 @@ msgstr "Nur diesen hervorheben"
msgid "External diff"
msgstr "Externer Vergleich"
#: gitk:2245
#: gitk:2255
msgid "Blame parent commit"
msgstr ""
msgstr "Annotieren der Elternversion"
#: gitk:2488
msgid ""
@@ -471,7 +479,33 @@ msgstr "<%s-Minus>\tSchriftgröße verkleinern"
msgid "<F5>\t\tUpdate"
msgstr "<F5>\t\tAktualisieren"
#: gitk:3200
#: gitk:2979
#, tcl-format
msgid "Error getting \"%s\" from %s:"
msgstr "Fehler beim Holen von »%s« von »%s«:"
#: gitk:3036 gitk:3045
#, tcl-format
msgid "Error creating temporary directory %s:"
msgstr "Fehler beim Erzeugen eines temporären Verzeichnisses »%s«:"
#: gitk:3058
msgid "command failed:"
msgstr "Kommando fehlgeschlagen:"
#: gitk:3078
msgid "No such commit"
msgstr "Version nicht gefunden"
#: gitk:3083
msgid "git gui blame: command failed:"
msgstr "git gui blame: Kommando fehlgeschlagen:"
#: gitk:3092
msgid "External diff viewer failed:"
msgstr "Externes Vergleich-(Diff-)Programm fehlgeschlagen:"
#: gitk:3210
msgid "Gitk view definition"
msgstr "Gitk Ansichten"
@@ -692,9 +726,10 @@ msgstr "Bitte geben Sie einen Namen für den neuen Zweig an."
#, tcl-format
msgid "Commit %s is already included in branch %s -- really re-apply it?"
msgstr ""
"Version »%s« ist bereits im Zweig »%s« enthalten -- trotzdem erneut eintragen?"
"Version »%s« ist bereits im Zweig »%s« enthalten -- trotzdem erneut "
"eintragen?"
#: gitk:7708
#: gitk:7718
msgid "Cherry-picking"
msgstr "Version pflücken"
@@ -836,7 +871,7 @@ msgstr "Vergleich nur für angezeigte Pfade"
#: gitk:9414
msgid "Support per-file encodings"
msgstr ""
msgstr "Zeichenkodierung pro Datei ermitteln"
#: gitk:9421
msgid "External diff tool"

View File

@@ -190,7 +190,9 @@ our %feature = (
# if there is no 'sub' key (no feature-sub), then feature cannot be
# overriden
#
# use gitweb_check_feature(<feature>) to check if <feature> is enabled
# use gitweb_get_feature(<feature>) to retrieve the <feature> value
# (an array) or gitweb_check_feature(<feature>) to check if <feature>
# is enabled
# Enable the 'blame' blob view, showing the last commit that modified
# each line in the file. This can be very CPU-intensive.
@@ -239,6 +241,7 @@ our %feature = (
# $feature{'grep'}{'override'} = 1;
# and in project config gitweb.grep = 0|1;
'grep' => {
'sub' => \&feature_grep,
'override' => 0,
'default' => [1]},
@@ -329,7 +332,7 @@ our %feature = (
'default' => [0]},
);
sub gitweb_check_feature {
sub gitweb_get_feature {
my ($name) = @_;
return unless exists $feature{$name};
my ($sub, $override, @defaults) = (
@@ -344,6 +347,22 @@ sub gitweb_check_feature {
return $sub->(@defaults);
}
# A wrapper to check if a given feature is enabled.
# With this, you can say
#
# my $bool_feat = gitweb_check_feature('bool_feat');
# gitweb_check_feature('bool_feat') or somecode;
#
# instead of
#
# my ($bool_feat) = gitweb_get_feature('bool_feat');
# (gitweb_get_feature('bool_feat'))[0] or somecode;
#
sub gitweb_check_feature {
return (gitweb_get_feature(@_))[0];
}
sub feature_blame {
my ($val) = git_get_project_config('blame', '--bool');
@@ -767,7 +786,7 @@ our $git_dir;
$git_dir = "$projectroot/$project" if $project;
# list of supported snapshot formats
our @snapshot_fmts = gitweb_check_feature('snapshot');
our @snapshot_fmts = gitweb_get_feature('snapshot');
@snapshot_fmts = filter_snapshot_fmts(@snapshot_fmts);
# dispatch
@@ -810,7 +829,7 @@ sub href (%) {
}
}
my ($use_pathinfo) = gitweb_check_feature('pathinfo');
my $use_pathinfo = gitweb_check_feature('pathinfo');
if ($use_pathinfo) {
# try to put as many parameters as possible in PATH_INFO:
# - project name
@@ -2101,7 +2120,7 @@ sub git_get_projects_list {
$filter ||= '';
$filter =~ s/\.git$//;
my ($check_forks) = gitweb_check_feature('forks');
my $check_forks = gitweb_check_feature('forks');
if (-d $projects_list) {
# search in directory
@@ -2740,6 +2759,15 @@ sub get_file_owner {
return to_utf8($owner);
}
# assume that file exists
sub insert_file {
my $filename = shift;
open my $fd, '<', $filename;
print map(to_utf8, <$fd>);
close $fd;
}
## ......................................................................
## mimetype related functions
@@ -2928,9 +2956,7 @@ EOF
"<body>\n";
if (-f $site_header) {
open (my $fd, $site_header);
print <$fd>;
close $fd;
insert_file($site_header);
}
print "<div class=\"page_header\">\n" .
@@ -2947,7 +2973,7 @@ EOF
}
print "</div>\n";
my ($have_search) = gitweb_check_feature('search');
my $have_search = gitweb_check_feature('search');
if (defined $project && $have_search) {
if (!defined $searchtext) {
$searchtext = "";
@@ -2961,7 +2987,7 @@ EOF
$search_hash = "HEAD";
}
my $action = $my_uri;
my ($use_pathinfo) = gitweb_check_feature('pathinfo');
my $use_pathinfo = gitweb_check_feature('pathinfo');
if ($use_pathinfo) {
$action .= "/".esc_url($project);
}
@@ -3017,9 +3043,7 @@ sub git_footer_html {
print "</div>\n"; # class="page_footer"
if (-f $site_footer) {
open (my $fd, $site_footer);
print <$fd>;
close $fd;
insert_file($site_footer);
}
print "</body>\n" .
@@ -3084,7 +3108,7 @@ sub git_print_page_nav {
$arg{'tree'}{'hash'} = $treehead if defined $treehead;
$arg{'tree'}{'hash_base'} = $treebase if defined $treebase;
my @actions = gitweb_check_feature('actions');
my @actions = gitweb_get_feature('actions');
my %repl = (
'%' => '%',
'n' => $project, # project name
@@ -3454,7 +3478,7 @@ sub is_patch_split {
sub git_difftree_body {
my ($difftree, $hash, @parents) = @_;
my ($parent) = $parents[0];
my ($have_blame) = gitweb_check_feature('blame');
my $have_blame = gitweb_check_feature('blame');
print "<div class=\"list_head\">\n";
if ($#{$difftree} > 10) {
print(($#{$difftree} + 1) . " files changed:\n");
@@ -3968,7 +3992,7 @@ sub git_project_list_body {
# actually uses global variable $project
my ($projlist, $order, $from, $to, $extra, $no_header) = @_;
my ($check_forks) = gitweb_check_feature('forks');
my $check_forks = gitweb_check_feature('forks');
my @projects = fill_project_list_info($projlist, $check_forks);
$order ||= $default_projects_order;
@@ -4358,9 +4382,7 @@ sub git_project_list {
git_header_html();
if (-f $home_text) {
print "<div class=\"index_include\">\n";
open (my $fd, $home_text);
print <$fd>;
close $fd;
insert_file($home_text);
print "</div>\n";
}
print $cgi->startform(-method => "get") .
@@ -4428,7 +4450,7 @@ sub git_summary {
my @taglist = git_get_tags_list(16);
my @headlist = git_get_heads_list(16);
my @forklist;
my ($check_forks) = gitweb_check_feature('forks');
my $check_forks = gitweb_check_feature('forks');
if ($check_forks) {
@forklist = git_get_projects_list($project);
@@ -4457,7 +4479,7 @@ sub git_summary {
}
# Tag cloud
my $show_ctags = (gitweb_check_feature('ctags'))[0];
my $show_ctags = gitweb_check_feature('ctags');
if ($show_ctags) {
my $ctags = git_get_project_ctags($project);
my $cloud = git_populate_project_tagcloud($ctags);
@@ -4472,13 +4494,10 @@ sub git_summary {
print "</table>\n";
if (-s "$projectroot/$project/README.html") {
if (open my $fd, "$projectroot/$project/README.html") {
print "<div class=\"title\">readme</div>\n" .
"<div class=\"readme\">\n";
print $_ while (<$fd>);
print "\n</div>\n"; # class="readme"
close $fd;
}
print "<div class=\"title\">readme</div>\n" .
"<div class=\"readme\">\n";
insert_file("$projectroot/$project/README.html");
print "\n</div>\n"; # class="readme"
}
# we need to request one more than 16 (0..15) to check if
@@ -4747,7 +4766,7 @@ sub git_blob {
$expires = "+1d";
}
my ($have_blame) = gitweb_check_feature('blame');
my $have_blame = gitweb_check_feature('blame');
open my $fd, "-|", git_cmd(), "cat-file", "blob", $hash
or die_error(500, "Couldn't cat $file_name, $hash");
my $mimetype = blob_mimetype($fd, $file_name);
@@ -4840,7 +4859,7 @@ sub git_tree {
my $ref = format_ref_marker($refs, $hash_base);
git_header_html();
my $basedir = '';
my ($have_blame) = gitweb_check_feature('blame');
my $have_blame = gitweb_check_feature('blame');
if (defined $hash_base && (my %co = parse_commit($hash_base))) {
my @views_nav = ();
if (defined $file_name) {
@@ -5838,7 +5857,7 @@ insensitive).</p>
<dt><b>commit</b></dt>
<dd>The commit messages and authorship information will be scanned for the given pattern.</dd>
EOT
my ($have_grep) = gitweb_check_feature('grep');
my $have_grep = gitweb_check_feature('grep');
if ($have_grep) {
print <<EOT;
<dt><b>grep</b></dt>
@@ -5855,7 +5874,7 @@ EOT
<dt><b>committer</b></dt>
<dd>Name and e-mail of the committer and date of commit will be scanned for the given pattern.</dd>
EOT
my ($have_pickaxe) = gitweb_check_feature('pickaxe');
my $have_pickaxe = gitweb_check_feature('pickaxe');
if ($have_pickaxe) {
print <<EOT;
<dt><b>pickaxe</b></dt>
@@ -5907,7 +5926,7 @@ sub git_shortlog {
sub git_feed {
my $format = shift || 'atom';
my ($have_blame) = gitweb_check_feature('blame');
my $have_blame = gitweb_check_feature('blame');
# Atom: http://www.atomenabled.org/developers/syndication/
# RSS: http://www.notestips.com/80256B3A007F2692/1/NAMO5P9UPQ

11
http.c
View File

@@ -24,7 +24,7 @@ static const char *ssl_cainfo = NULL;
static long curl_low_speed_limit = -1;
static long curl_low_speed_time = -1;
static int curl_ftp_no_epsv = 0;
static char *curl_http_proxy = NULL;
static const char *curl_http_proxy = NULL;
static struct curl_slist *pragma_header;
@@ -149,11 +149,8 @@ static int http_options(const char *var, const char *value, void *cb)
return 0;
}
if (!strcmp("http.proxy", var)) {
if (curl_http_proxy == NULL) {
if (!value)
return config_error_nonbool(var);
curl_http_proxy = xstrdup(value);
}
if (curl_http_proxy == NULL)
return git_config_string(&curl_http_proxy, var, value);
return 0;
}
@@ -309,7 +306,7 @@ void http_cleanup(void)
pragma_header = NULL;
if (curl_http_proxy) {
free(curl_http_proxy);
free((void *)curl_http_proxy);
curl_http_proxy = NULL;
}
}

View File

@@ -121,6 +121,7 @@ static int crud(unsigned char c)
c == '<' ||
c == '>' ||
c == '"' ||
c == '\\' ||
c == '\'';
}

View File

@@ -525,7 +525,8 @@ static void update_file_flags(struct merge_options *o,
char *lnk = xmemdupz(buf, size);
safe_create_leading_directories_const(path);
unlink(path);
symlink(lnk, path);
if (symlink(lnk, path))
die("failed to symlink %s: %s", path, strerror(errno));
free(lnk);
} else
die("do not know what to do with %06o %s '%s'",

View File

@@ -2,6 +2,14 @@
* Copyright (C) 2008 Linus Torvalds
*/
#include "cache.h"
#ifdef NO_PTHREADS
static void preload_index(struct index_state *index, const char **pathspec)
{
; /* nothing */
}
#else
#include <pthread.h>
/*
@@ -81,6 +89,7 @@ static void preload_index(struct index_state *index, const char **pathspec)
die("unable to join threaded lstat");
}
}
#endif
int read_index_preload(struct index_state *index, const char **pathspec)
{

View File

@@ -257,6 +257,14 @@ int ie_match_stat(const struct index_state *istate,
if (!ignore_valid && (ce->ce_flags & CE_VALID))
return 0;
/*
* Intent-to-add entries have not been added, so the index entry
* by definition never matches what is in the work tree until it
* actually gets added.
*/
if (ce->ce_flags & CE_INTENT_TO_ADD)
return DATA_CHANGED | TYPE_CHANGED | MODE_CHANGED;
changed = ce_match_stat_basic(ce, st);
/*
@@ -546,6 +554,8 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
ce->ce_flags = namelen;
if (!intent_only)
fill_stat_cache_info(ce, st);
else
ce->ce_flags |= CE_INTENT_TO_ADD;
if (trust_executable_bit && has_symlinks)
ce->ce_mode = create_ce_mode(st_mode);
@@ -1098,7 +1108,7 @@ static int verify_hdr(struct cache_header *hdr, unsigned long size)
if (hdr->hdr_signature != htonl(CACHE_SIGNATURE))
return error("bad signature");
if (hdr->hdr_version != htonl(2))
if (hdr->hdr_version != htonl(2) && hdr->hdr_version != htonl(3))
return error("bad index version");
git_SHA1_Init(&c);
git_SHA1_Update(&c, hdr, size - 20);
@@ -1133,6 +1143,7 @@ int read_index(struct index_state *istate)
static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_entry *ce)
{
size_t len;
const char *name;
ce->ce_ctime = ntohl(ondisk->ctime.sec);
ce->ce_mtime = ntohl(ondisk->mtime.sec);
@@ -1145,19 +1156,31 @@ static void convert_from_disk(struct ondisk_cache_entry *ondisk, struct cache_en
/* On-disk flags are just 16 bits */
ce->ce_flags = ntohs(ondisk->flags);
/* For future extension: we do not understand this entry yet */
if (ce->ce_flags & CE_EXTENDED)
die("Unknown index entry format");
hashcpy(ce->sha1, ondisk->sha1);
len = ce->ce_flags & CE_NAMEMASK;
if (ce->ce_flags & CE_EXTENDED) {
struct ondisk_cache_entry_extended *ondisk2;
int extended_flags;
ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
extended_flags = ntohs(ondisk2->flags2) << 16;
/* We do not yet understand any bit out of CE_EXTENDED_FLAGS */
if (extended_flags & ~CE_EXTENDED_FLAGS)
die("Unknown index entry format %08x", extended_flags);
ce->ce_flags |= extended_flags;
name = ondisk2->name;
}
else
name = ondisk->name;
if (len == CE_NAMEMASK)
len = strlen(ondisk->name);
len = strlen(name);
/*
* NEEDSWORK: If the original index is crafted, this copy could
* go unchecked.
*/
memcpy(ce->name, ondisk->name, len + 1);
memcpy(ce->name, name, len + 1);
}
static inline size_t estimate_cache_size(size_t ondisk_size, unsigned int entries)
@@ -1422,6 +1445,7 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce)
{
int size = ondisk_ce_size(ce);
struct ondisk_cache_entry *ondisk = xcalloc(1, size);
char *name;
ondisk->ctime.sec = htonl(ce->ce_ctime);
ondisk->ctime.nsec = 0;
@@ -1435,7 +1459,15 @@ static int ce_write_entry(git_SHA_CTX *c, int fd, struct cache_entry *ce)
ondisk->size = htonl(ce->ce_size);
hashcpy(ondisk->sha1, ce->sha1);
ondisk->flags = htons(ce->ce_flags);
memcpy(ondisk->name, ce->name, ce_namelen(ce));
if (ce->ce_flags & CE_EXTENDED) {
struct ondisk_cache_entry_extended *ondisk2;
ondisk2 = (struct ondisk_cache_entry_extended *)ondisk;
ondisk2->flags2 = htons((ce->ce_flags & CE_EXTENDED_FLAGS) >> 16);
name = ondisk2->name;
}
else
name = ondisk->name;
memcpy(name, ce->name, ce_namelen(ce));
return ce_write(c, fd, ondisk, size);
}
@@ -1444,16 +1476,25 @@ int write_index(const struct index_state *istate, int newfd)
{
git_SHA_CTX c;
struct cache_header hdr;
int i, err, removed;
int i, err, removed, extended;
struct cache_entry **cache = istate->cache;
int entries = istate->cache_nr;
for (i = removed = 0; i < entries; i++)
for (i = removed = extended = 0; i < entries; i++) {
if (cache[i]->ce_flags & CE_REMOVE)
removed++;
/* reduce extended entries if possible */
cache[i]->ce_flags &= ~CE_EXTENDED;
if (cache[i]->ce_flags & CE_EXTENDED_FLAGS) {
extended++;
cache[i]->ce_flags |= CE_EXTENDED;
}
}
hdr.hdr_signature = htonl(CACHE_SIGNATURE);
hdr.hdr_version = htonl(2);
/* for extended format, increase version so older git won't try to read it */
hdr.hdr_version = htonl(extended ? 3 : 2);
hdr.hdr_entries = htonl(entries - removed);
git_SHA1_Init(&c);

View File

@@ -70,6 +70,19 @@ static int write_rr(struct string_list *rr, int out_fd)
return 0;
}
static void ferr_write(const void *p, size_t count, FILE *fp, int *err)
{
if (!count || *err)
return;
if (fwrite(p, count, 1, fp) != 1)
*err = errno;
}
static inline void ferr_puts(const char *s, FILE *fp, int *err)
{
ferr_write(s, strlen(s), fp, err);
}
static int handle_file(const char *path,
unsigned char *sha1, const char *output)
{
@@ -82,6 +95,7 @@ static int handle_file(const char *path,
struct strbuf one = STRBUF_INIT, two = STRBUF_INIT;
FILE *f = fopen(path, "r");
FILE *out = NULL;
int wrerror = 0;
if (!f)
return error("Could not open %s", path);
@@ -118,11 +132,11 @@ static int handle_file(const char *path,
hunk_no++;
hunk = RR_CONTEXT;
if (out) {
fputs("<<<<<<<\n", out);
fwrite(one.buf, one.len, 1, out);
fputs("=======\n", out);
fwrite(two.buf, two.len, 1, out);
fputs(">>>>>>>\n", out);
ferr_puts("<<<<<<<\n", out, &wrerror);
ferr_write(one.buf, one.len, out, &wrerror);
ferr_puts("=======\n", out, &wrerror);
ferr_write(two.buf, two.len, out, &wrerror);
ferr_puts(">>>>>>>\n", out, &wrerror);
}
if (sha1) {
git_SHA1_Update(&ctx, one.buf ? one.buf : "",
@@ -139,7 +153,7 @@ static int handle_file(const char *path,
else if (hunk == RR_SIDE_2)
strbuf_addstr(&two, buf);
else if (out)
fputs(buf, out);
ferr_puts(buf, out, &wrerror);
continue;
bad:
hunk = 99; /* force error exit */
@@ -149,8 +163,12 @@ static int handle_file(const char *path,
strbuf_release(&two);
fclose(f);
if (out)
fclose(out);
if (wrerror)
error("There were errors while writing %s (%s)",
path, strerror(wrerror));
if (out && fclose(out))
wrerror = error("Failed to flush %s: %s",
path, strerror(errno));
if (sha1)
git_SHA1_Final(sha1, &ctx);
if (hunk != RR_CONTEXT) {
@@ -158,6 +176,8 @@ static int handle_file(const char *path,
unlink(output);
return error("Could not parse conflict hunks in %s", path);
}
if (wrerror)
return -1;
return hunk_no;
}
@@ -200,9 +220,13 @@ static int merge(const char *name, const char *path)
if (!ret) {
FILE *f = fopen(path, "w");
if (!f)
return error("Could not write to %s", path);
fwrite(result.ptr, result.size, 1, f);
fclose(f);
return error("Could not open %s: %s", path,
strerror(errno));
if (fwrite(result.ptr, result.size, 1, f) != 1)
error("Could not write %s: %s", path, strerror(errno));
if (fclose(f))
return error("Writing %s failed: %s", path,
strerror(errno));
}
free(cur.ptr);

View File

@@ -470,7 +470,8 @@ const char *setup_git_directory_gently(int *nongit_ok)
}
die("Not a git repository");
}
chdir("..");
if (chdir(".."))
die("Cannot change to %s/..: %s", cwd, strerror(errno));
}
inside_git_dir = 0;

View File

@@ -32,5 +32,33 @@ test_expect_success 'intent to add does not clobber existing paths' '
! grep "$empty" actual
'
test_expect_success 'cannot commit with i-t-a entry' '
test_tick &&
git commit -a -m initial &&
git reset --hard &&
echo xyzzy >rezrov &&
echo frotz >nitfol &&
git add rezrov &&
git add -N nitfol &&
test_must_fail git commit
'
test_expect_success 'can commit with an unrelated i-t-a entry in index' '
git reset --hard &&
echo xyzzy >rezrov &&
echo frotz >nitfol &&
git add rezrov &&
git add -N nitfol &&
git commit -m partial rezrov
'
test_expect_success 'can "commit -a" with an i-t-a entry' '
git reset --hard &&
: >nitfol &&
git add -N nitfol &&
git commit -a -m all
'
test_done

View File

@@ -187,8 +187,8 @@ test_expect_success 'but with -f it should work.' '
test_must_fail git ls-files --error-unmatch baz
'
test_expect_failure 'refuse to remove cached empty file with modifications' '
touch empty &&
test_expect_success 'refuse to remove cached empty file with modifications' '
>empty &&
git add empty &&
echo content >empty &&
test_must_fail git rm --cached empty

View File

@@ -29,7 +29,7 @@ test_expect_success 'setup binary file with history' '
printf "\\0\\n" >file &&
git add file &&
git commit -m one &&
printf "\\1\\n" >>file &&
printf "\\01\\n" >>file &&
git add file &&
git commit -m two
'

53
t/t4252-am-options.sh Executable file
View File

@@ -0,0 +1,53 @@
#!/bin/sh
test_description='git am not losing options'
. ./test-lib.sh
tm="$TEST_DIRECTORY/t4252"
test_expect_success setup '
cp "$tm/file-1-0" file-1 &&
cp "$tm/file-2-0" file-2 &&
git add file-1 file-2 &&
test_tick &&
git commit -m initial &&
git tag initial
'
test_expect_success 'interrupted am --whitespace=fix' '
rm -rf .git/rebase-apply &&
git reset --hard initial &&
test_must_fail git am --whitespace=fix "$tm"/am-test-1-? &&
git am --skip &&
grep 3 file-1 &&
grep "^Six$" file-2
'
test_expect_success 'interrupted am -C1' '
rm -rf .git/rebase-apply &&
git reset --hard initial &&
test_must_fail git am -C1 "$tm"/am-test-2-? &&
git am --skip &&
grep 3 file-1 &&
grep "^Three$" file-2
'
test_expect_success 'interrupted am -p2' '
rm -rf .git/rebase-apply &&
git reset --hard initial &&
test_must_fail git am -p2 "$tm"/am-test-3-? &&
git am --skip &&
grep 3 file-1 &&
grep "^Three$" file-2
'
test_expect_success 'interrupted am -C1 -p2' '
rm -rf .git/rebase-apply &&
git reset --hard initial &&
test_must_fail git am -p2 -C1 "$tm"/am-test-4-? &&
git am --skip &&
grep 3 file-1 &&
grep "^Three$" file-2
'
test_done

19
t/t4252/am-test-1-1 Normal file
View File

@@ -0,0 +1,19 @@
From: A U Thor <au.thor@example.com>
Date: Thu Dec 4 16:00:00 2008 -0800
Subject: Three
Application of this should be rejected because the first line in the
context does not match.
diff --git i/file-1 w/file-1
index 06e567b..10f8342 100644
--- i/file-1
+++ w/file-1
@@ -1,6 +1,6 @@
One
2
-3
+Three
4
5
6

21
t/t4252/am-test-1-2 Normal file
View File

@@ -0,0 +1,21 @@
From: A U Thor <au.thor@example.com>
Date: Thu Dec 4 16:00:00 2008 -0800
Subject: Six
Applying this patch with --whitespace=fix should lose
the trailing whitespace after "Six".
diff --git i/file-2 w/file-2
index 06e567b..b6f3a16 100644
--- i/file-2
+++ w/file-2
@@ -1,7 +1,7 @@
1
2
-3
+Three
4
5
-6
+Six
7

19
t/t4252/am-test-2-1 Normal file
View File

@@ -0,0 +1,19 @@
From: A U Thor <au.thor@example.com>
Date: Thu Dec 4 16:00:00 2008 -0800
Subject: Three
Application of this should be rejected even with -C1 because the
preimage line in the context does not match.
diff --git i/file-1 w/file-1
index 06e567b..10f8342 100644
--- i/file-1
+++ w/file-1
@@ -1,6 +1,6 @@
1
2
-Tres
+Three
4
5
6

21
t/t4252/am-test-2-2 Normal file
View File

@@ -0,0 +1,21 @@
From: A U Thor <au.thor@example.com>
Date: Thu Dec 4 16:00:00 2008 -0800
Subject: Six
Applying this patch with -C1 should be successful even though
the first line in the context does not match.
diff --git i/file-2 w/file-2
index 06e567b..b6f3a16 100644
--- i/file-2
+++ w/file-2
@@ -1,7 +1,7 @@
One
2
-3
+Three
4
5
-6
+Six
7

19
t/t4252/am-test-3-1 Normal file
View File

@@ -0,0 +1,19 @@
From: A U Thor <au.thor@example.com>
Date: Thu Dec 4 16:00:00 2008 -0800
Subject: Three
Application of this should be rejected even with -p2 because the
preimage line in the context does not match.
diff --git i/junk/file-1 w/junk/file-1
index 06e567b..10f8342 100644
--- i/junk/file-1
+++ w/junk/file-1
@@ -1,6 +1,6 @@
1
2
-Tres
+Three
4
5
6

21
t/t4252/am-test-3-2 Normal file
View File

@@ -0,0 +1,21 @@
From: A U Thor <au.thor@example.com>
Date: Thu Dec 4 16:00:00 2008 -0800
Subject: Six
Applying this patch with -p2 should be successful even though
the patch is against a wrong level.
diff --git i/junk/file-2 w/junk/file-2
index 06e567b..b6f3a16 100644
--- i/junk/file-2
+++ w/junk/file-2
@@ -1,7 +1,7 @@
1
2
-3
+Three
4
5
-6
+Six
7

19
t/t4252/am-test-4-1 Normal file
View File

@@ -0,0 +1,19 @@
From: A U Thor <au.thor@example.com>
Date: Thu Dec 4 16:00:00 2008 -0800
Subject: Three
Application of this should be rejected even with -C1 -p2 because
the preimage line in the context does not match.
diff --git i/junk/file-1 w/junk/file-1
index 06e567b..10f8342 100644
--- i/junk/file-1
+++ w/junk/file-1
@@ -1,6 +1,6 @@
1
2
-Tres
+Three
4
5
6

22
t/t4252/am-test-4-2 Normal file
View File

@@ -0,0 +1,22 @@
From: A U Thor <au.thor@example.com>
Date: Thu Dec 4 16:00:00 2008 -0800
Subject: Six
Applying this patch with -C1 -p2 should be successful even though
the patch is against a wrong level and the first context line does
not match.
diff --git i/junk/file-2 w/junk/file-2
index 06e567b..b6f3a16 100644
--- i/junk/file-2
+++ w/junk/file-2
@@ -1,7 +1,7 @@
One
2
-3
+Three
4
5
-6
+Six
7

7
t/t4252/file-1-0 Normal file
View File

@@ -0,0 +1,7 @@
1
2
3
4
5
6
7

7
t/t4252/file-2-0 Normal file
View File

@@ -0,0 +1,7 @@
1
2
3
4
5
6
7

View File

@@ -313,8 +313,25 @@ test_expect_success 'bisect run & skip: find first bad' '
grep "$HASH6 is first bad commit" my_bisect_log.txt
'
test_expect_success 'bisect starting with a detached HEAD' '
test_expect_success 'bisect skip only one range' '
git bisect reset &&
git bisect start $HASH7 $HASH1 &&
git bisect skip $HASH1..$HASH5 &&
test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
test_must_fail git bisect bad > my_bisect_log.txt &&
grep "first bad commit could be any of" my_bisect_log.txt
'
test_expect_success 'bisect skip many ranges' '
git bisect start $HASH7 $HASH1 &&
test "$HASH4" = "$(git rev-parse --verify HEAD)" &&
git bisect skip $HASH2 $HASH2.. ..$HASH5 &&
test "$HASH6" = "$(git rev-parse --verify HEAD)" &&
test_must_fail git bisect bad > my_bisect_log.txt &&
grep "first bad commit could be any of" my_bisect_log.txt
'
test_expect_success 'bisect starting with a detached HEAD' '
git bisect reset &&
git checkout master^ &&
HEAD=$(git rev-parse --verify HEAD) &&

View File

@@ -56,4 +56,23 @@ test_expect_success 'git svn branch tests' '
test_must_fail git svn tag tag1
'
test_expect_success 'branch uses correct svn-remote' '
(svn co "$svnrepo" svn &&
cd svn &&
mkdir mirror &&
svn add mirror &&
svn copy trunk mirror/ &&
svn copy tags mirror/ &&
svn copy branches mirror/ &&
svn ci -m "made mirror" ) &&
rm -rf svn &&
git svn init -s -R mirror --prefix=mirror/ "$svnrepo"/mirror &&
git svn fetch -R mirror &&
git checkout mirror/trunk &&
base=$(git rev-parse HEAD:) &&
git svn branch -m "branch in mirror" d &&
test $base = $(git rev-parse remotes/mirror/d:) &&
test_must_fail git rev-parse remotes/d
'
test_done