提交 79a9d8ea 编写于 作者: P Peter Anvin

Merge with master.kernel.org:/pub/scm/git/git.git

......@@ -82,6 +82,7 @@ git-ssh-push
git-ssh-upload
git-status
git-stripspace
git-symbolic-ref
git-tag
git-tar-tree
git-unpack-file
......
......@@ -9,7 +9,7 @@ git-clone - Clones a repository.
SYNOPSIS
--------
'git clone' [-l] [-u <upload-pack>] [-q] <repository> <directory>
'git clone' [-l [-s]] [-q] [-n] [-u <upload-pack>] <repository> <directory>
DESCRIPTION
-----------
......@@ -17,6 +17,7 @@ Clones a repository into a newly created directory.
OPTIONS
-------
--local::
-l::
When the repository to clone from is on a local machine,
this flag bypasses normal "git aware" transport
......@@ -25,10 +26,22 @@ OPTIONS
The files under .git/objects/ directory are hardlinked
to save space when possible.
--shared::
-s::
When the repository to clone is on the local machine,
instead of using hard links automatically setup
.git/objects/info/alternatives to share the objects
with the source repository
--quiet::
-q::
Operate quietly. This flag is passed to "rsync" and
"git-clone-pack" commands when given.
-n::
No checkout of HEAD is performed after the clone is complete.
--upload-pack <upload-pack>::
-u <upload-pack>::
When given, and the repository to clone from is handled
by 'git-clone-pack', '--exec=<upload-pack>' is passed to
......
......@@ -13,7 +13,7 @@ SYNOPSIS
(-[c|d|o|i|s|u|k|m])\*
[-x <pattern>|--exclude=<pattern>]
[-X <file>|--exclude-from=<file>]
[--exclude-per-directory=<file>]
[--exclude-per-directory=<file>] [--] [<file>]\*
DESCRIPTION
-----------
......@@ -77,6 +77,13 @@ OPTIONS
K to be killed
? other
--::
Do not interpret any more arguments as options.
<file>::
Files to show. If no files are given all files which match the other
specified criteria are shown.
Output
------
show files just outputs the filename unless '--stage' is specified in
......
......@@ -50,7 +50,7 @@
# DEFINES += -DUSE_STDEV
GIT_VERSION = 0.99.7.GIT
GIT_VERSION = 0.99.8.GIT
CFLAGS = -g -O2 -Wall
ALL_CFLAGS = $(CFLAGS) $(PLATFORM_DEFINES) $(DEFINES)
......@@ -103,25 +103,29 @@ SIMPLE_PROGRAMS = \
# ... and all the rest
PROGRAMS = \
git-apply$X git-cat-file$X git-checkout-index$X \
git-clone-pack$X git-commit-tree$X git-convert-objects$X \
git-diff-files$X git-diff-index$X git-diff-stages$X \
git-diff-tree$X git-fetch-pack$X git-fsck-objects$X \
git-hash-object$X git-init-db$X git-local-fetch$X \
git-ls-files$X git-ls-tree$X git-merge-base$X \
git-merge-index$X git-mktag$X git-pack-objects$X \
git-patch-id$X git-peek-remote$X git-prune-packed$X \
git-read-tree$X git-receive-pack$X git-rev-list$X \
git-rev-parse$X git-send-pack$X git-show-branch$X \
git-show-index$X git-ssh-fetch$X git-ssh-upload$X \
git-tar-tree$X git-unpack-file$X git-unpack-objects$X \
git-update-index$X git-update-server-info$X \
git-upload-pack$X git-verify-pack$X git-write-tree$X \
git-update-ref$X $(SIMPLE_PROGRAMS)
git-apply$X git-cat-file$X \
git-checkout-index$X git-clone-pack$X git-commit-tree$X \
git-convert-objects$X git-diff-files$X \
git-diff-index$X git-diff-stages$X \
git-diff-tree$X git-fetch-pack$X git-fsck-objects$X \
git-hash-object$X git-init-db$X \
git-local-fetch$X git-ls-files$X git-ls-tree$X git-merge-base$X \
git-merge-index$X git-mktag$X git-pack-objects$X git-patch-id$X \
git-peek-remote$X git-prune-packed$X git-read-tree$X \
git-receive-pack$X git-rev-list$X git-rev-parse$X \
git-send-pack$X git-show-branch$X \
git-show-index$X git-ssh-fetch$X \
git-ssh-upload$X git-tar-tree$X git-unpack-file$X \
git-unpack-objects$X git-update-index$X git-update-server-info$X \
git-upload-pack$X git-verify-pack$X git-write-tree$X \
git-update-ref$X git-symbolic-ref$X \
$(SIMPLE_PROGRAMS)
# Backward compatibility -- to be removed after 1.0
PROGRAMS += git-ssh-pull$X git-ssh-push$X
GIT_LIST_TWEAK =
PYMODULES = \
gitMergeCommon.py
......@@ -131,6 +135,8 @@ endif
ifdef WITH_SEND_EMAIL
SCRIPT_PERL += git-send-email.perl
else
GIT_LIST_TWEAK += -e '/^send-email$$/d'
endif
LIB_FILE=libgit.a
......@@ -181,6 +187,10 @@ endif
ifneq (,$(findstring arm,$(shell uname -m)))
ARM_SHA1 = YesPlease
endif
ifeq ($(shell uname -s),OpenBSD)
NEEDS_LIBICONV = YesPlease
PLATFORM_DEFINES += -I/usr/local/include -L/usr/local/lib
endif
ifndef NO_CURL
ifdef CURLDIR
......@@ -206,18 +216,32 @@ endif
ifndef NO_OPENSSL
LIB_OBJS += epoch.o
OPENSSL_LIBSSL = -lssl
ifdef OPENSSLDIR
# Again this may be problematic -- gcc does not always want -R.
CFLAGS += -I$(OPENSSLDIR)/include
OPENSSL_LINK = -L$(OPENSSLDIR)/lib -R$(OPENSSLDIR)/lib
else
OPENSSL_LINK =
endif
else
DEFINES += '-DNO_OPENSSL'
MOZILLA_SHA1 = 1
OPENSSL_LIBSSL =
endif
ifdef NEEDS_SSL_WITH_CRYPTO
LIB_4_CRYPTO = -lcrypto -lssl
LIB_4_CRYPTO = $(OPENSSL_LINK) -lcrypto -lssl
else
LIB_4_CRYPTO = -lcrypto
LIB_4_CRYPTO = $(OPENSSL_LINK) -lcrypto
endif
ifdef NEEDS_LIBICONV
LIB_4_ICONV = -liconv
ifdef ICONVDIR
# Again this may be problematic -- gcc does not always want -R.
CFLAGS += -I$(ICONVDIR)/include
ICONV_LINK = -L$(ICONVDIR)/lib -R$(ICONVDIR)/lib
else
ICONV_LINK =
endif
LIB_4_ICONV = $(ICONV_LINK) -liconv
else
LIB_4_ICONV =
endif
......@@ -273,8 +297,13 @@ all:
git: git.sh Makefile
rm -f $@+ $@
sed -e '1s|#!.*/sh|#!$(SHELL_PATH)|' \
<<<<<<< Makefile
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-e 's/@@X@@/$(X)/g' <$@.sh >$@+
=======
-e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
$(GIT_LIST_TWEAK) <$@.sh >$@+
>>>>>>> .merge_file_3QHyD4
chmod +x $@+
mv $@+ $@
......
......@@ -723,6 +723,16 @@ static int parse_single_patch(char *line, unsigned long size, struct patch *patc
return offset;
}
static inline int metadata_changes(struct patch *patch)
{
return patch->is_rename > 0 ||
patch->is_copy > 0 ||
patch->is_new > 0 ||
patch->is_delete ||
(patch->old_mode && patch->new_mode &&
patch->old_mode != patch->new_mode);
}
static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
{
int hdrsize, patchsize;
......@@ -733,6 +743,9 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
patchsize = parse_single_patch(buffer + offset + hdrsize, size - offset - hdrsize, patch);
if (!patchsize && !metadata_changes(patch))
die("patch with only garbage at line %d", linenr);
return offset + hdrsize + patchsize;
}
......
......@@ -189,6 +189,7 @@ extern char *git_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)
extern char *sha1_file_name(const unsigned char *sha1);
extern char *sha1_pack_name(const unsigned char *sha1);
extern char *sha1_pack_index_name(const unsigned char *sha1);
extern const unsigned char null_sha1[20];
int git_mkstemp(char *path, size_t n, const char *template);
......@@ -228,6 +229,10 @@ extern int has_pack_index(const unsigned char *sha1);
extern int get_sha1(const char *str, unsigned char *sha1);
extern int get_sha1_hex(const char *hex, unsigned char *sha1);
extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */
extern int read_ref(const char *filename, unsigned char *sha1);
extern const char *resolve_ref(const char *path, unsigned char *sha1, int);
extern int create_symref(const char *git_HEAD, const char *refs_heads_master);
extern int validate_symref(const char *git_HEAD);
/* General helper functions */
extern void usage(const char *err) NORETURN;
......
git-core (0.99.8-0) unstable; urgency=low
* GIT 0.99.8
-- Junio C Hamano <junkio@cox.net> Sun, 2 Oct 2005 12:54:26 -0700
git-core (0.99.7-0) unstable; urgency=low
* GIT 0.99.7
......
......@@ -34,7 +34,6 @@ static void show_modified(int oldmode, int mode,
int main(int argc, const char **argv)
{
static const unsigned char null_sha1[20] = { 0, };
const char **pathspec;
const char *prefix = setup_git_directory();
int entries, i;
......
......@@ -10,7 +10,6 @@
#include "diffcore.h"
static const char *diff_opts = "-pu";
static unsigned char null_sha1[20] = { 0, };
static int use_size_cache;
......@@ -414,7 +413,7 @@ void diff_free_filespec_data(struct diff_filespec *s)
static void prep_temp_blob(struct diff_tempfile *temp,
void *blob,
unsigned long size,
unsigned char *sha1,
const unsigned char *sha1,
int mode)
{
int fd;
......
......@@ -402,25 +402,17 @@ static void fsck_object_dir(const char *path)
static int fsck_head_link(void)
{
int fd, count;
char hex[40];
unsigned char sha1[20];
static char path[PATH_MAX], link[PATH_MAX];
const char *git_dir = get_git_dir();
snprintf(path, sizeof(path), "%s/HEAD", git_dir);
if (readlink(path, link, sizeof(link)) < 0)
return error("HEAD is not a symlink");
if (strncmp("refs/heads/", link, 11))
return error("HEAD points to something strange (%s)", link);
fd = open(path, O_RDONLY);
if (fd < 0)
return error("HEAD: %s", strerror(errno));
count = read(fd, hex, sizeof(hex));
close(fd);
if (count < 0)
return error("HEAD: %s", strerror(errno));
if (count < 40 || get_sha1_hex(hex, sha1))
const char *git_HEAD = strdup(git_path("HEAD"));
const char *git_refs_heads_master = resolve_ref(git_HEAD, sha1, 1);
int pfxlen = strlen(git_HEAD) - 4; /* strip .../.git/ part */
if (!git_refs_heads_master)
return error("HEAD is not a symbolic ref");
if (strncmp(git_refs_heads_master + pfxlen, "refs/heads/", 11))
return error("HEAD points to something strange (%s)",
git_refs_heads_master + pfxlen);
if (!memcmp(null_sha1, sha1, 20))
return error("HEAD: not a valid git pointer");
return 0;
}
......
......@@ -228,10 +228,12 @@ END
# skip commits already in repo
#
if (ptag($ps->{id})) {
$opt_v && print "Skipping already imported: $ps->{id}\n";
$opt_v && print " * Skipping already imported: $ps->{id}\n";
next;
}
print " * Starting to work on $ps->{id}\n";
#
# create the branch if needed
#
......@@ -675,6 +677,10 @@ sub find_parents {
# that branch.
#
foreach my $branch (keys %branches) {
# check that we actually know about the branch
next unless -e "$git_dir/refs/heads/$branch";
my $mergebase = `git-merge-base $branch $ps->{branch}`;
die "Cannot find merge base for $branch and $ps->{branch}" if $?;
chomp $mergebase;
......
......@@ -38,7 +38,8 @@ bisect_start() {
# Verify HEAD. If we were bisecting before this, reset to the
# top-of-line master first!
#
head=$(readlink $GIT_DIR/HEAD) || die "Bad HEAD - I need a symlink"
head=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD) ||
die "Bad HEAD - I need a symbolic ref"
case "$head" in
refs/heads/bisect*)
git checkout master || exit
......@@ -46,7 +47,7 @@ bisect_start() {
refs/heads/*)
;;
*)
die "Bad HEAD - strange symlink"
die "Bad HEAD - strange symbolic ref"
;;
esac
......@@ -135,7 +136,7 @@ bisect_next() {
echo "$rev" > "$GIT_DIR/refs/heads/new-bisect"
git checkout new-bisect || exit
mv "$GIT_DIR/refs/heads/new-bisect" "$GIT_DIR/refs/heads/bisect" &&
ln -sf refs/heads/bisect "$GIT_DIR/HEAD"
GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD refs/heads/bisect
git-show-branch "$rev"
}
......
......@@ -14,7 +14,8 @@ If two arguments, create a new branch <branchname> based off of <start-point>.
delete_branch () {
option="$1" branch_name="$2"
headref=$(readlink "$GIT_DIR/HEAD" | sed -e 's|^refs/heads/||')
headref=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD |
sed -e 's|^refs/heads/||')
case ",$headref," in
",$branch_name,")
die "Cannot delete the branch you are on." ;;
......@@ -67,7 +68,8 @@ done
case "$#" in
0)
headref=$(readlink "$GIT_DIR/HEAD" | sed -e 's|^refs/heads/||')
headref=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD |
sed -e 's|^refs/heads/||')
git-rev-parse --symbolic --all |
sed -ne 's|^refs/heads/||p' |
sort |
......
......@@ -71,7 +71,8 @@ if [ "$?" -eq 0 ]; then
echo $new > "$GIT_DIR/refs/heads/$newbranch"
branch="$newbranch"
fi
[ "$branch" ] && ln -sf "refs/heads/$branch" "$GIT_DIR/HEAD"
[ "$branch" ] &&
GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD "refs/heads/$branch"
rm -f "$GIT_DIR/MERGE_HEAD"
else
exit 1
......
......@@ -153,15 +153,8 @@ if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
fi >>.editmsg
PARENTS="-p HEAD"
if [ ! -r "$GIT_DIR/HEAD" ]; then
if [ -z "$(git-ls-files)" ]; then
echo Nothing to commit 1>&2
exit 1
fi
PARENTS=""
current=
else
current=$(git-rev-parse --verify HEAD)
if GIT_DIR="$GIT_DIR" git-rev-parse --verify HEAD >/dev/null 2>&1
then
if [ -f "$GIT_DIR/MERGE_HEAD" ]; then
PARENTS="-p HEAD "`sed -e 's/^/-p /' "$GIT_DIR/MERGE_HEAD"`
fi
......@@ -194,6 +187,12 @@ else
export GIT_AUTHOR_EMAIL
export GIT_AUTHOR_DATE
fi
else
if [ -z "$(git-ls-files)" ]; then
echo Nothing to commit 1>&2
exit 1
fi
PARENTS=""
fi
git-status >>.editmsg
if [ "$?" != "0" -a ! -f $GIT_DIR/MERGE_HEAD ]
......
......@@ -510,7 +510,7 @@ ($$)
my $state = 0;
my($patchset,$date,$author,$branch,$ancestor,$tag,$logmsg);
my($patchset,$date,$author_name,$author_email,$branch,$ancestor,$tag,$logmsg);
my(@old,@new);
my $commit = sub {
my $pid;
......@@ -591,11 +591,11 @@ ($$)
}
exec("env",
"GIT_AUTHOR_NAME=$author",
"GIT_AUTHOR_EMAIL=$author",
"GIT_AUTHOR_NAME=$author_name",
"GIT_AUTHOR_EMAIL=$author_email",
"GIT_AUTHOR_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)),
"GIT_COMMITTER_NAME=$author",
"GIT_COMMITTER_EMAIL=$author",
"GIT_COMMITTER_NAME=$author_name",
"GIT_COMMITTER_EMAIL=$author_email",
"GIT_COMMITTER_DATE=".strftime("+0000 %Y-%m-%d %H:%M:%S",gmtime($date)),
"git-commit-tree", $tree,@par);
die "Cannot exec git-commit-tree: $!\n";
......@@ -638,7 +638,7 @@ ($$)
print $out "object $cid\n".
"type commit\n".
"tag $xtag\n".
"tagger $author <$author>\n"
"tagger $author_name <$author_email>\n"
or die "Cannot create tag object $xtag: $!\n";
close($out)
or die "Cannot create tag object $xtag: $!\n";
......@@ -683,7 +683,11 @@ ($$)
$state=3;
} elsif($state == 3 and s/^Author:\s+//) {
s/\s+$//;
$author = $_;
if (/^(.*?)\s+<(.*)>/) {
($author_name, $author_email) = ($1, $2);
} else {
$author_name = $author_email = $_;
}
$state = 4;
} elsif($state == 4 and s/^Branch:\s+//) {
s/\s+$//;
......
......@@ -5,6 +5,7 @@
_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
tags=
append=
force=
update_head_ok=
......@@ -17,6 +18,9 @@ do
-f|--f|--fo|--for|--forc|--force)
force=t
;;
-t|--t|--ta|--tag|--tags)
tags=t
;;
-u|--u|--up|--upd|--upda|--updat|--update|--update-|--update-h|\
--update-he|--update-hea|--update-head|--update-head-|\
--update-head-o|--update-head-ok)
......@@ -158,7 +162,26 @@ case "$update_head_ok" in
;;
esac
for ref in $(get_remote_refs_for_fetch "$@")
# If --tags (and later --heads or --all) is specified, then we are
# not talking about defaults stored in Pull: line of remotes or
# branches file, and just fetch those and refspecs explicitly given.
# Otherwise we do what we always did.
reflist=$(get_remote_refs_for_fetch "$@")
if test "$tags"
then
taglist=$(git-ls-remote --tags "$remote" | awk '{ print "."$2":"$2 }')
if test "$#" -gt 1
then
# remote URL plus explicit refspecs; we need to merge them.
reflist="$reflist $taglist"
else
# No explicit refspecs; fetch tags only.
reflist=$taglist
fi
fi
for ref in $reflist
do
refs="$refs $ref"
......
此差异已折叠。
......@@ -123,10 +123,30 @@ case "$#,$common" in
dropsave
exit 0
;;
1,*)
1,?*"$LF"?*)
# We are not doing octopus and not fast forward. Need a
# real merge.
;;
1,*)
# We are not doing octopus, not fast forward, and have only
# one common. See if it is really trivial.
echo "Trying really trivial in-index merge..."
git-update-index --refresh 2>/dev/null
if git-read-tree --trivial -m -u $common $head "$1" &&
result_tree=$(git-write-tree)
then
echo "Wonderful."
result_commit=$(
echo "$merge_msg" |
git-commit-tree $result_tree -p HEAD -p "$1"
) || exit
git-update-ref HEAD $result_commit $head
summary $result_commit
dropsave
exit 0
fi
echo "Nope."
;;
*)
# An octopus. If we can reach all the remote we are up to date.
up_to_date=t
......
......@@ -13,10 +13,13 @@
unset CDPATH
die() {
echo "$@" >&2
echo >&2 "$@"
exit 1
}
[ -h "$GIT_DIR/HEAD" ] &&
case "$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD 2>/dev/null)" in
refs/*) : ;;
*) false ;;
esac &&
[ -d "$GIT_DIR/refs" ] &&
[ -d "$GIT_OBJECT_DIRECTORY/00" ]
......@@ -31,15 +31,15 @@ report () {
[ "$header" ]
}
branch=`readlink "$GIT_DIR/HEAD"`
branch=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD)
case "$branch" in
refs/heads/master) ;;
*) echo "# On branch $branch" ;;
esac
git-update-index --refresh >/dev/null 2>&1
git-update-index -q --unmerged --refresh || exit
if test -f "$GIT_DIR/HEAD"
if GIT_DIR="$GIT_DIR" git-rev-parse --verify HEAD >/dev/null 2>&1
then
git-diff-index -M --cached HEAD |
sed 's/^://' |
......
......@@ -26,17 +26,50 @@ esac
echo "Usage: git COMMAND [OPTIONS] [TARGET]"
if [ -n "$cmd" ]; then
echo " git command '$cmd' not found: commands are:"
else
echo " git commands are:"
echo "git command '$cmd' not found."
fi
echo "git commands are:"
cat <<\EOF
add apply archimport bisect branch checkout cherry clone
commit count-objects cvsimport diff fetch format-patch
fsck-cache get-tar-commit-id init-db log ls-remote octopus
pack-objects parse-remote patch-id prune pull push rebase
relink rename repack request-pull reset resolve revert
send-email shortlog show-branch status tag verify-tag
whatchanged
fmt <<\EOF | sed -e 's/^/ /'
add
apply
archimport
bisect
branch
checkout
cherry
clone
commit
count-objects
cvsimport
diff
fetch
format-patch
fsck-objects
get-tar-commit-id
init-db
log
ls-remote
octopus
pack-objects
parse-remote
patch-id
prune
pull
push
rebase
relink
rename
repack
request-pull
reset
resolve
revert
send-email
shortlog
show-branch
status
tag
verify-tag
whatchanged
EOF
#include "cache.h"
#include "commit.h"
#include "pack.h"
#include "fetch.h"
#include <curl/curl.h>
......@@ -13,8 +13,12 @@
#define curl_global_init(a) do { /* nothing */ } while(0)
#endif
#define PREV_BUF_SIZE 4096
#define RANGE_HEADER_SIZE 30
static CURL *curl;
static struct curl_slist *no_pragma_header;
static struct curl_slist *no_range_header;
static char curl_errorstr[CURL_ERROR_SIZE];
static char *initial_base;
......@@ -87,12 +91,37 @@ void prefetch(unsigned char *sha1)
{
}
int relink_or_rename(char *old, char *new) {
int ret;
ret = link(old, new);
if (ret < 0) {
/* Same Coda hack as in write_sha1_file(sha1_file.c) */
ret = errno;
if (ret == EXDEV && !rename(old, new))
return 0;
}
unlink(old);
if (ret) {
if (ret != EEXIST)
return ret;
}
return 0;
}
static int got_alternates = 0;
static int fetch_index(struct alt_base *repo, unsigned char *sha1)
{
char *filename;
char *url;
char tmpfile[PATH_MAX];
int ret;
long prev_posn = 0;
char range[RANGE_HEADER_SIZE];
struct curl_slist *range_header = NULL;
CURLcode curl_result;
FILE *indexfile;
......@@ -108,7 +137,8 @@ static int fetch_index(struct alt_base *repo, unsigned char *sha1)
repo->base, sha1_to_hex(sha1));
filename = sha1_pack_index_name(sha1);
indexfile = fopen(filename, "w");
snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
indexfile = fopen(tmpfile, "a");
if (!indexfile)
return error("Unable to open local file %s for pack index",
filename);
......@@ -119,13 +149,36 @@ static int fetch_index(struct alt_base *repo, unsigned char *sha1)
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_pragma_header);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errorstr);
if (curl_easy_perform(curl)) {
/* If there is data present from a previous transfer attempt,
resume where it left off */
prev_posn = ftell(indexfile);
if (prev_posn>0) {
if (get_verbosely)
fprintf(stderr,
"Resuming fetch of index for pack %s at byte %ld\n",
sha1_to_hex(sha1), prev_posn);
sprintf(range, "Range: bytes=%ld-", prev_posn);
range_header = curl_slist_append(range_header, range);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, range_header);
}
/* Clear out the Range: header after performing the request, so
other curl requests don't inherit inappropriate header data */
curl_result = curl_easy_perform(curl);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_range_header);
if (curl_result != 0) {
fclose(indexfile);
return error("Unable to get pack index %s\n%s", url,
curl_errorstr);
}
fclose(indexfile);
ret = relink_or_rename(tmpfile, filename);
if (ret)
return error("unable to write index filename %s: %s",
filename, strerror(ret));
return 0;
}
......@@ -306,6 +359,12 @@ static int fetch_pack(struct alt_base *repo, unsigned char *sha1)
struct packed_git **lst;
FILE *packfile;
char *filename;
char tmpfile[PATH_MAX];
int ret;
long prev_posn = 0;
char range[RANGE_HEADER_SIZE];
struct curl_slist *range_header = NULL;
CURLcode curl_result;
if (fetch_indices(repo))
return -1;
......@@ -325,7 +384,8 @@ static int fetch_pack(struct alt_base *repo, unsigned char *sha1)
repo->base, sha1_to_hex(target->sha1));
filename = sha1_pack_name(target->sha1);
packfile = fopen(filename, "w");
snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
packfile = fopen(tmpfile, "a");
if (!packfile)
return error("Unable to open local file %s for pack",
filename);
......@@ -336,7 +396,24 @@ static int fetch_pack(struct alt_base *repo, unsigned char *sha1)
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_pragma_header);
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errorstr);
if (curl_easy_perform(curl)) {
/* If there is data present from a previous transfer attempt,
resume where it left off */
prev_posn = ftell(packfile);
if (prev_posn>0) {
if (get_verbosely)
fprintf(stderr,
"Resuming fetch of pack %s at byte %ld\n",
sha1_to_hex(target->sha1), prev_posn);
sprintf(range, "Range: bytes=%ld-", prev_posn);
range_header = curl_slist_append(range_header, range);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, range_header);
}
/* Clear out the Range: header after performing the request, so
other curl requests don't inherit inappropriate header data */
curl_result = curl_easy_perform(curl);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_range_header);
if (curl_result != 0) {
fclose(packfile);
return error("Unable to get pack file %s\n%s", url,
curl_errorstr);
......@@ -344,11 +421,18 @@ static int fetch_pack(struct alt_base *repo, unsigned char *sha1)
fclose(packfile);
ret = relink_or_rename(tmpfile, filename);
if (ret)
return error("unable to write pack filename %s: %s",
filename, strerror(ret));
lst = &repo->packs;
while (*lst != target)
lst = &((*lst)->next);
*lst = (*lst)->next;
if (verify_pack(target, 0))
return -1;
install_packed_git(target);
return 0;
......@@ -360,14 +444,33 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1)
char *filename = sha1_file_name(sha1);
unsigned char real_sha1[20];
char tmpfile[PATH_MAX];
char prevfile[PATH_MAX];
int ret;
char *url;
char *posn;
int prevlocal;
unsigned char prev_buf[PREV_BUF_SIZE];
ssize_t prev_read = 0;
long prev_posn = 0;
char range[RANGE_HEADER_SIZE];
struct curl_slist *range_header = NULL;
CURLcode curl_result;
snprintf(tmpfile, sizeof(tmpfile), "%s.temp", filename);
snprintf(prevfile, sizeof(prevfile), "%s.prev", filename);
if (unlink(prevfile) && (errno != ENOENT))
return error("Failed to unlink %s (%s)",
prevfile, strerror(errno));
if (rename(tmpfile, prevfile) && (errno != ENOENT))
return error("Failed to rename %s to %s (%s)",
tmpfile, prevfile, strerror(errno));
snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX",
get_object_directory());
local = open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
/* Note: if another instance starts now, it will turn our new
tmpfile into its prevfile. */
local = mkstemp(tmpfile);
if (local < 0)
return error("Couldn't create temporary file %s for %s: %s\n",
tmpfile, filename, strerror(errno));
......@@ -396,8 +499,57 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1)
curl_easy_setopt(curl, CURLOPT_URL, url);
if (curl_easy_perform(curl)) {
unlink(filename);
/* If a previous temp file is present, process what was already
fetched. */
prevlocal = open(prevfile, O_RDONLY);
if (prevlocal != -1) {
do {
prev_read = read(prevlocal, prev_buf, PREV_BUF_SIZE);
if (prev_read>0) {
if (fwrite_sha1_file(prev_buf,
1,
prev_read,
NULL) == prev_read) {
prev_posn += prev_read;
} else {
prev_read = -1;
}
}
} while (prev_read > 0);
close(prevlocal);
}
unlink(prevfile);
/* Reset inflate/SHA1 if there was an error reading the previous temp
file; also rewind to the beginning of the local file. */
if (prev_read == -1) {
memset(&stream, 0, sizeof(stream));
inflateInit(&stream);
SHA1_Init(&c);
if (prev_posn>0) {
prev_posn = 0;
lseek(local, SEEK_SET, 0);
ftruncate(local, 0);
}
}
/* If we have successfully processed data from a previous fetch
attempt, only fetch the data we don't already have. */
if (prev_posn>0) {
if (get_verbosely)
fprintf(stderr,
"Resuming fetch of object %s at byte %ld\n",
hex, prev_posn);
sprintf(range, "Range: bytes=%ld-", prev_posn);
range_header = curl_slist_append(range_header, range);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, range_header);
}
/* Clear out the Range: header after performing the request, so
other curl requests don't inherit inappropriate header data */
curl_result = curl_easy_perform(curl);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, no_range_header);
if (curl_result != 0) {
return error("%s", curl_errorstr);
}
......@@ -413,20 +565,11 @@ static int fetch_object(struct alt_base *repo, unsigned char *sha1)
unlink(tmpfile);
return error("File %s has bad hash\n", hex);
}
ret = link(tmpfile, filename);
if (ret < 0) {
/* Same Coda hack as in write_sha1_file(sha1_file.c) */
ret = errno;
if (ret == EXDEV && !rename(tmpfile, filename))
goto out;
}
unlink(tmpfile);
if (ret) {
if (ret != EEXIST)
return error("unable to write sha1 filename %s: %s",
filename, strerror(ret));
}
out:
ret = relink_or_rename(tmpfile, filename);
if (ret)
return error("unable to write sha1 filename %s: %s",
filename, strerror(ret));
pull_say("got %s\n", hex);
return 0;
}
......@@ -519,6 +662,7 @@ int main(int argc, char **argv)
curl = curl_easy_init();
no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:");
no_range_header = curl_slist_append(no_range_header, "Range:");
curl_ssl_verify = getenv("GIT_SSL_NO_VERIFY") ? 0 : 1;
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, curl_ssl_verify);
......
......@@ -29,7 +29,7 @@ int hold_index_file_for_update(struct cache_file *cf, const char *path)
signal(SIGINT, remove_lock_file_on_signal);
atexit(remove_lock_file);
}
return open(cf->lockfile, O_RDWR | O_CREAT | O_EXCL, 0600);
return open(cf->lockfile, O_RDWR | O_CREAT | O_EXCL, 0666);
}
int commit_index_file(struct cache_file *cf)
......
......@@ -166,6 +166,7 @@ static void create_default_files(const char *git_dir,
{
unsigned len = strlen(git_dir);
static char path[PATH_MAX];
unsigned char sha1[20];
if (len > sizeof(path)-50)
die("insane git directory %s", git_dir);
......@@ -186,15 +187,14 @@ static void create_default_files(const char *git_dir,
/*
* Create the default symlink from ".git/HEAD" to the "master"
* branch
* branch, if it does not exist yet.
*/
strcpy(path + len, "HEAD");
if (symlink("refs/heads/master", path) < 0) {
if (errno != EEXIST) {
perror(path);
if (read_ref(path, sha1) < 0) {
if (create_symref(path, "refs/heads/master") < 0)
exit(1);
}
}
path[len] = 0;
copy_templates(path, len, template_path);
}
......
......@@ -530,7 +530,7 @@ static void verify_pathspec(void)
static const char ls_files_usage[] =
"git-ls-files [-z] [-t] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
"[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
"[ --exclude-per-directory=<filename> ]";
"[ --exclude-per-directory=<filename> ] [--] [<file>]*";
int main(int argc, const char **argv)
{
......@@ -544,6 +544,10 @@ int main(int argc, const char **argv)
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
if (!strcmp(arg, "--")) {
i++;
break;
}
if (!strcmp(arg, "-z")) {
line_terminator = 0;
continue;
......
......@@ -128,7 +128,7 @@ int main(int argc, char **argv)
unsigned long len = parse_email(map, size);
assert(len <= size);
sprintf(name, "%04d", ++nr);
fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0600);
fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0666);
if (fd < 0) {
perror(name);
exit(1);
......
......@@ -464,11 +464,15 @@ int read_cache(void)
errno = EBUSY;
if (active_cache)
return error("more than one cachefile");
return active_nr;
errno = ENOENT;
fd = open(get_index_file(), O_RDONLY);
if (fd < 0)
return (errno == ENOENT) ? 0 : error("open failed");
if (fd < 0) {
if (errno == ENOENT)
return 0;
die("index file open failed (%s)", strerror(errno));
}
size = 0; // avoid gcc warning
map = MAP_FAILED;
......@@ -480,7 +484,7 @@ int read_cache(void)
}
close(fd);
if (map == MAP_FAILED)
return error("mmap failed");
die("index file mmap failed (%s)", strerror(errno));
hdr = map;
if (verify_hdr(hdr, size) < 0)
......@@ -501,7 +505,7 @@ int read_cache(void)
unmap:
munmap(map, size);
errno = EINVAL;
return error("verify header failed");
die("index file corrupt");
}
#define WRITE_BUFFER_SIZE 8192
......
......@@ -13,6 +13,8 @@
static int merge = 0;
static int update = 0;
static int index_only = 0;
static int nontrivial_merge = 0;
static int trivial_merges_only = 0;
static int head_idx = -1;
static int merge_size = 0;
......@@ -275,6 +277,9 @@ static int unpack_trees(merge_fn_t fn)
if (unpack_trees_rec(posns, len, "", fn, &indpos))
return -1;
if (trivial_merges_only && nontrivial_merge)
die("Merge requires file-level merging");
check_updates(active_cache, active_nr);
return 0;
}
......@@ -460,6 +465,8 @@ static int threeway_merge(struct cache_entry **stages)
verify_uptodate(index);
}
nontrivial_merge = 1;
/* #2, #3, #4, #6, #7, #9, #11. */
count = 0;
if (!head_match || !remote_match) {
......@@ -629,9 +636,9 @@ int main(int argc, char **argv)
continue;
}
if (!strcmp(arg, "--head")) {
head_idx = stage - 1;
fn = threeway_merge;
if (!strcmp(arg, "--trivial")) {
trivial_merges_only = 1;
continue;
}
/* "-m" stands for "merge", meaning we start in stage 1 */
......@@ -657,7 +664,8 @@ int main(int argc, char **argv)
}
if ((update||index_only) && !merge)
usage(read_tree_usage);
if (merge && !fn) {
if (merge) {
if (stage < 2)
die("just how do you expect me to merge %d trees?", stage-1);
switch (stage - 1) {
......@@ -674,9 +682,7 @@ int main(int argc, char **argv)
fn = threeway_merge;
break;
}
}
if (head_idx < 0) {
if (stage - 1 >= 3)
head_idx = stage - 2;
else
......
......@@ -2,19 +2,157 @@
#include "cache.h"
#include <errno.h>
#include <ctype.h>
static int read_ref(const char *refname, unsigned char *sha1)
/* We allow "recursive" symbolic refs. Only within reason, though */
#define MAXDEPTH 5
#ifndef USE_SYMLINK_HEAD
#define USE_SYMLINK_HEAD 1
#endif
int validate_symref(const char *path)
{
int ret = -1;
int fd = open(git_path("%s", refname), O_RDONLY);
struct stat st;
char *buf, buffer[256];
int len, fd;
if (lstat(path, &st) < 0)
return -1;
/* Make sure it is a "refs/.." symlink */
if (S_ISLNK(st.st_mode)) {
len = readlink(path, buffer, sizeof(buffer)-1);
if (len >= 5 && !memcmp("refs/", buffer, 5))
return 0;
return -1;
}
/*
* Anything else, just open it and try to see if it is a symbolic ref.
*/
fd = open(path, O_RDONLY);
if (fd < 0)
return -1;
len = read(fd, buffer, sizeof(buffer)-1);
close(fd);
/*
* Is it a symbolic ref?
*/
if (len < 4 || memcmp("ref:", buffer, 4))
return -1;
buf = buffer + 4;
len -= 4;
while (len && isspace(*buf))
buf++, len--;
if (len >= 5 && !memcmp("refs/", buffer, 5))
return 0;
return -1;
}
if (fd >= 0) {
char buffer[60];
if (read(fd, buffer, sizeof(buffer)) >= 40)
ret = get_sha1_hex(buffer, sha1);
const char *resolve_ref(const char *path, unsigned char *sha1, int reading)
{
int depth = MAXDEPTH, len;
char buffer[256];
for (;;) {
struct stat st;
char *buf;
int fd;
if (--depth < 0)
return NULL;
/* Special case: non-existing file.
* Not having the refs/heads/new-branch is OK
* if we are writing into it, so is .git/HEAD
* that points at refs/heads/master still to be
* born. It is NOT OK if we are resolving for
* reading.
*/
if (lstat(path, &st) < 0) {
if (reading || errno != ENOENT)
return NULL;
memset(sha1, 0, 20);
return path;
}
/* Follow "normalized" - ie "refs/.." symlinks by hand */
if (S_ISLNK(st.st_mode)) {
len = readlink(path, buffer, sizeof(buffer)-1);
if (len >= 5 && !memcmp("refs/", buffer, 5)) {
path = git_path("%.*s", len, buffer);
continue;
}
}
/*
* Anything else, just open it and try to use it as
* a ref
*/
fd = open(path, O_RDONLY);
if (fd < 0)
return NULL;
len = read(fd, buffer, sizeof(buffer)-1);
close(fd);
/*
* Is it a symbolic ref?
*/
if (len < 4 || memcmp("ref:", buffer, 4))
break;
buf = buffer + 4;
len -= 4;
while (len && isspace(*buf))
buf++, len--;
while (len && isspace(buf[len-1]))
buf[--len] = 0;
path = git_path("%.*s", len, buf);
}
return ret;
if (len < 40 || get_sha1_hex(buffer, sha1))
return NULL;
return path;
}
int create_symref(const char *git_HEAD, const char *refs_heads_master)
{
#if USE_SYMLINK_HEAD
unlink(git_HEAD);
return symlink(refs_heads_master, git_HEAD);
#else
const char *lockpath;
char ref[1000];
int fd, len, written;
len = snprintf(ref, sizeof(ref), "ref: %s\n", refs_heads_master);
if (sizeof(ref) <= len) {
error("refname too long: %s", refs_heads_master);
return -1;
}
lockpath = mkpath("%s.lock", git_HEAD);
fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);
written = write(fd, ref, len);
close(fd);
if (written != len) {
unlink(lockpath);
error("Unable to write to %s", lockpath);
return -2;
}
if (rename(lockpath, git_HEAD) < 0) {
unlink(lockpath);
error("Unable to create %s", git_HEAD);
return -3;
}
return 0;
#endif
}
int read_ref(const char *filename, unsigned char *sha1)
{
if (resolve_ref(filename, sha1, 1))
return 0;
return -1;
}
static int do_for_each_ref(const char *base, int (*fn)(const char *path, const unsigned char *sha1))
......@@ -54,7 +192,7 @@ static int do_for_each_ref(const char *base, int (*fn)(const char *path, const u
break;
continue;
}
if (read_ref(path, sha1) < 0)
if (read_ref(git_path("%s", path), sha1) < 0)
continue;
if (!has_sha1_file(sha1))
continue;
......@@ -71,7 +209,7 @@ static int do_for_each_ref(const char *base, int (*fn)(const char *path, const u
int head_ref(int (*fn)(const char *path, const unsigned char *sha1))
{
unsigned char sha1[20];
if (!read_ref("HEAD", sha1))
if (!read_ref(git_path("HEAD"), sha1))
return fn("HEAD", sha1);
return 0;
}
......@@ -101,33 +239,14 @@ static char *ref_lock_file_name(const char *ref)
return ret;
}
static int read_ref_file(const char *filename, unsigned char *sha1) {
int fd = open(filename, O_RDONLY);
char hex[41];
if (fd < 0) {
return error("Couldn't open %s\n", filename);
}
if ((read(fd, hex, 41) < 41) ||
(hex[40] != '\n') ||
get_sha1_hex(hex, sha1)) {
error("Couldn't read a hash from %s\n", filename);
close(fd);
return -1;
}
close(fd);
return 0;
}
int get_ref_sha1(const char *ref, unsigned char *sha1)
{
char *filename;
int retval;
const char *filename;
if (check_ref_format(ref))
return -1;
filename = ref_file_name(ref);
retval = read_ref_file(filename, sha1);
free(filename);
return retval;
filename = git_path("refs/%s", ref);
return read_ref(filename, sha1);
}
static int lock_ref_file(const char *filename, const char *lock_filename,
......@@ -140,7 +259,7 @@ static int lock_ref_file(const char *filename, const char *lock_filename,
return error("Couldn't open lock file for %s: %s",
filename, strerror(errno));
}
retval = read_ref_file(filename, current_sha1);
retval = read_ref(filename, current_sha1);
if (old_sha1) {
if (retval) {
close(fd);
......
......@@ -76,18 +76,20 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
* Test it it looks like we're at the top
* level git directory. We want to see a
*
* - a HEAD symlink and a refs/ directory under ".git"
* - either a .git/objects/ directory _or_ the proper
* GIT_OBJECT_DIRECTORY environment variable
* - a refs/ directory under ".git"
* - either a HEAD symlink or a HEAD file that is formatted as
* a proper "ref:".
*/
static int is_toplevel_directory(void)
{
struct stat st;
return !lstat(".git/HEAD", &st) &&
S_ISLNK(st.st_mode) &&
!access(".git/refs/", X_OK) &&
(getenv(DB_ENVIRONMENT) || !access(".git/objects/", X_OK));
if (access(".git/refs/", X_OK) ||
access(getenv(DB_ENVIRONMENT) ?
getenv(DB_ENVIRONMENT) : ".git/objects/", X_OK) ||
validate_symref(".git/HEAD"))
return 0;
return 1;
}
const char *setup_git_directory(void)
......
......@@ -20,6 +20,8 @@
#endif
#endif
const unsigned char null_sha1[20] = { 0, };
static unsigned int sha1_file_open_flag = O_NOATIME;
static unsigned hexval(char c)
......
......@@ -119,21 +119,6 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1)
return -1;
}
static int get_sha1_file(const char *path, unsigned char *result)
{
char buffer[60];
int fd = open(path, O_RDONLY);
int len;
if (fd < 0)
return -1;
len = read(fd, buffer, sizeof(buffer));
close(fd);
if (len < 40)
return -1;
return get_sha1_hex(buffer, result);
}
static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
{
static const char *prefix[] = {
......@@ -150,7 +135,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
for (p = prefix; *p; p++) {
char *pathname = git_path("%s/%.*s", *p, len, str);
if (!get_sha1_file(pathname, sha1))
if (!read_ref(pathname, sha1))
return 0;
}
......
......@@ -349,6 +349,7 @@ int main(int ac, char **av)
int all_heads = 0, all_tags = 0;
int all_mask, all_revs, shown_merge_point;
char head_path[128];
const char *head_path_p;
int head_path_len;
unsigned char head_sha1[20];
int merge_base = 0;
......@@ -430,11 +431,15 @@ int main(int ac, char **av)
if (0 <= extra)
join_revs(&list, &seen, num_rev, extra);
head_path_len = readlink(".git/HEAD", head_path, sizeof(head_path)-1);
if ((head_path_len < 0) || get_sha1("HEAD", head_sha1))
head_path_p = resolve_ref(git_path("HEAD"), head_sha1, 1);
if (head_path_p) {
head_path_len = strlen(head_path_p);
memcpy(head_path, head_path_p, head_path_len + 1);
}
else {
head_path_len = 0;
head_path[0] = 0;
else
head_path[head_path_len] = 0;
}
if (merge_base)
return show_merge_base(seen, num_rev);
......
#include "cache.h"
static const char git_symbolic_ref_usage[] =
"git-symbolic-ref name [ref]";
static int check_symref(const char *HEAD)
{
unsigned char sha1[20];
const char *git_HEAD = strdup(git_path("%s", HEAD));
const char *git_refs_heads_master = resolve_ref(git_HEAD, sha1, 0);
if (git_refs_heads_master) {
/* we want to strip the .git/ part */
int pfxlen = strlen(git_HEAD) - strlen(HEAD);
puts(git_refs_heads_master + pfxlen);
}
else
die("No such ref: %s", HEAD);
}
int main(int argc, const char **argv)
{
setup_git_directory();
switch (argc) {
case 2:
check_symref(argv[1]);
break;
case 3:
create_symref(strdup(git_path("%s", argv[1])), argv[2]);
break;
default:
usage(git_symbolic_ref_usage);
}
return 0;
}
......@@ -5,6 +5,7 @@
#GIT_TEST_OPTS=--verbose --debug
SHELL_PATH ?= $(SHELL)
TAR ?= $(TAR)
T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
......
#!/bin/sh
#
# Copyright (c) 2005 Junio C Hamano
#
test_description='git-ls-files test (-- to terminate the path list).
This test runs git-ls-files --others with the following on the
filesystem.
path0 - a file
-foo - a file with a funny name.
-- - another file with a funny name.
'
. ./test-lib.sh
test_expect_success \
setup \
'echo frotz >path0 &&
echo frotz >./-foo &&
echo frotz >./--'
test_expect_success \
'git-ls-files without path restriction.' \
'git-ls-files --others >output &&
diff -u output - <<EOF
--
-foo
output
path0
EOF
'
test_expect_success \
'git-ls-files with path restriction.' \
'git-ls-files --others path0 >output &&
diff -u output - <<EOF
path0
EOF
'
test_expect_success \
'git-ls-files with path restriction with --.' \
'git-ls-files --others -- path0 >output &&
diff -u output - <<EOF
path0
EOF
'
test_expect_success \
'git-ls-files with path restriction with -- --.' \
'git-ls-files --others -- -- >output &&
diff -u output - <<EOF
--
EOF
'
test_expect_success \
'git-ls-files with no path restriction.' \
'git-ls-files --others -- >output &&
diff -u output - <<EOF
--
-foo
output
path0
EOF
'
test_done
......@@ -50,7 +50,7 @@ test_expect_success \
test_expect_success \
'validate file modification time' \
'TZ=GMT tar tvf b.tar a/a |
'TZ=GMT $TAR tvf b.tar a/a |
awk \{print\ \$4,\ \(length\(\$5\)\<7\)\ ?\ \$5\":00\"\ :\ \$5\} \
>b.mtime &&
echo "2005-05-27 22:00:00" >expected.mtime &&
......@@ -63,7 +63,7 @@ test_expect_success \
test_expect_success \
'extract tar archive' \
'(cd b && tar xf -) <b.tar'
'(cd b && $TAR xf -) <b.tar'
test_expect_success \
'validate filenames' \
......@@ -80,7 +80,7 @@ test_expect_success \
test_expect_success \
'extract tar archive with prefix' \
'(cd c && tar xf -) <c.tar'
'(cd c && $TAR xf -) <c.tar'
test_expect_success \
'validate filenames with prefix' \
......
......@@ -20,12 +20,12 @@ test_expect_success setup '
commit=$(echo "Commit #$i" | git-commit-tree $tree -p $parent) &&
parent=$commit || return 1
done &&
echo "$commit" >.git/HEAD &&
git-update-ref HEAD "$commit" &&
git-clone -l ./. victim &&
cd victim &&
git-log &&
cd .. &&
echo $zero >.git/HEAD &&
git-update-ref HEAD "$zero" &&
parent=$zero &&
for i in $cnt
do
......@@ -33,7 +33,7 @@ test_expect_success setup '
commit=$(echo "Rebase #$i" | git-commit-tree $tree -p $parent) &&
parent=$commit || return 1
done &&
echo "$commit" >.git/HEAD &&
git-update-ref HEAD "$commit" &&
echo Rebase &&
git-log'
......
......@@ -7,20 +7,6 @@ test_description='Tests git-rev-list --bisect functionality'
. ./test-lib.sh
. ../t6000lib.sh # t6xxx specific functions
bc_expr()
{
bc <<EOF
scale=1
define abs(x) {
if (x>=0) { return (x); } else { return (-x); }
}
define floor(x) {
save=scale; scale=0; result=x/1; scale=save; return (result);
}
$*
EOF
}
# usage: test_bisection max-diff bisect-option head ^prune...
#
# e.g. test_bisection 1 --bisect l1 ^l0
......@@ -35,8 +21,19 @@ test_bisection_diff()
_head=$1
shift 1
_bisection_size=$(git-rev-list $_bisection "$@" | wc -l)
[ -n "$_list_size" -a -n "$_bisection_size" ] || error "test_bisection_diff failed"
test_expect_success "bisection diff $_bisect_option $_head $* <= $_max_diff" "[ $(bc_expr "floor(abs($_list_size/2)-$_bisection_size)") -le $_max_diff ]"
[ -n "$_list_size" -a -n "$_bisection_size" ] ||
error "test_bisection_diff failed"
# Test if bisection size is close to half of list size within
# tolerance.
#
_bisect_err=`expr $_list_size - $_bisection_size \* 2`
test "$_bisect_err" -lt 0 && _bisect_err=`expr 0 - $_bisect_err`
_bisect_err=`expr $_bisect_err / 2` ; # floor
test_expect_success \
"bisection diff $_bisect_option $_head $* <= $_max_diff" \
'test $_bisect_err -le $_max_diff'
}
date >path0
......
......@@ -353,6 +353,8 @@ static void traverse_tree(void *buffer, unsigned long size,
if (size < namelen + 20 || sscanf(buffer, "%o", &mode) != 1)
die("corrupt 'tree' file");
if (S_ISDIR(mode) || S_ISREG(mode))
mode |= (mode & 0100) ? 0777 : 0666;
buffer = sha1 + 20;
size -= namelen + 20;
......
......@@ -13,7 +13,7 @@
* like "git-update-index *" and suddenly having all the object
* files be revision controlled.
*/
static int allow_add = 0, allow_remove = 0, allow_replace = 0, not_new = 0, quiet = 0, info_only = 0;
static int allow_add = 0, allow_remove = 0, allow_replace = 0, allow_unmerged = 0, not_new = 0, quiet = 0, info_only = 0;
static int force_remove;
/* Three functions to allow overloaded pointer return; see linux/err.h */
......@@ -135,7 +135,7 @@ static struct cache_entry *refresh_entry(struct cache_entry *ce)
changed = ce_match_stat(ce, &st);
if (!changed)
return ce;
return NULL;
if (ce_modified(ce, &st))
return ERR_PTR(-EINVAL);
......@@ -156,16 +156,20 @@ static int refresh_cache(void)
struct cache_entry *ce, *new;
ce = active_cache[i];
if (ce_stage(ce)) {
printf("%s: needs merge\n", ce->name);
has_errors = 1;
while ((i < active_nr) &&
! strcmp(active_cache[i]->name, ce->name))
i++;
i--;
if (allow_unmerged)
continue;
printf("%s: needs merge\n", ce->name);
has_errors = 1;
continue;
}
new = refresh_entry(ce);
if (!new)
continue;
if (IS_ERR(new)) {
if (not_new && PTR_ERR(new) == -ENOENT)
continue;
......@@ -335,6 +339,10 @@ int main(int argc, const char **argv)
allow_remove = 1;
continue;
}
if (!strcmp(path, "--unmerged")) {
allow_unmerged = 1;
continue;
}
if (!strcmp(path, "--refresh")) {
has_errors |= refresh_cache();
continue;
......@@ -383,9 +391,11 @@ int main(int argc, const char **argv)
update_one(buf.buf, prefix, prefix_length);
}
}
if (write_cache(newfd, active_cache, active_nr) ||
commit_index_file(&cache_file))
die("Unable to write new cachefile");
if (active_cache_changed) {
if (write_cache(newfd, active_cache, active_nr) ||
commit_index_file(&cache_file))
die("Unable to write new cachefile");
}
return has_errors ? 1 : 0;
}
......@@ -4,53 +4,6 @@
static const char git_update_ref_usage[] = "git-update-ref <refname> <value> [<oldval>]";
#define MAXDEPTH 5
static const char *resolve_ref(const char *path, unsigned char *sha1)
{
int depth = MAXDEPTH, len;
char buffer[256];
for (;;) {
struct stat st;
int fd;
if (--depth < 0)
return NULL;
/* Special case: non-existing file */
if (lstat(path, &st) < 0) {
if (errno != ENOENT)
return NULL;
memset(sha1, 0, 20);
return path;
}
/* Follow "normalized" - ie "refs/.." symlinks by hand */
if (S_ISLNK(st.st_mode)) {
len = readlink(path, buffer, sizeof(buffer)-1);
if (len >= 5 && !memcmp("refs/", buffer, 5)) {
path = git_path("%.*s", len, buffer);
continue;
}
}
/*
* Anything else, just open it and try to use it as
* a ref
*/
fd = open(path, O_RDONLY);
if (fd < 0)
return NULL;
len = read(fd, buffer, sizeof(buffer)-1);
close(fd);
break;
}
if (len < 40 || get_sha1_hex(buffer, sha1))
return NULL;
return path;
}
static int re_verify(const char *path, unsigned char *oldsha1, unsigned char *currsha1)
{
char buf[40];
......@@ -84,7 +37,7 @@ int main(int argc, char **argv)
if (oldval && get_sha1(oldval, oldsha1) < 0)
die("%s: not a valid old SHA1", oldval);
path = resolve_ref(git_path("%s", refname), currsha1);
path = resolve_ref(git_path("%s", refname), currsha1, !!oldval);
if (!path)
die("No such ref: %s", refname);
......
......@@ -15,7 +15,7 @@ static void report(const char *prefix, const char *err, va_list params)
void usage(const char *err)
{
fprintf(stderr, "usage: %s\n", err);
exit(1);
exit(129);
}
void die(const char *err, ...)
......@@ -25,7 +25,7 @@ void die(const char *err, ...)
va_start(params, err);
report("fatal: ", err, params);
va_end(params);
exit(1);
exit(128);
}
int error(const char *err, ...)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册