summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes-1.5.0.5.txt28
-rw-r--r--Documentation/config.txt4
-rw-r--r--builtin-branch.c39
-rw-r--r--builtin-pack-objects.c14
-rw-r--r--cache.h9
-rw-r--r--config.c4
-rwxr-xr-xgit-applymbox.sh4
-rwxr-xr-xgit-checkout.sh2
-rwxr-xr-xgit-fetch.sh12
-rwxr-xr-xgit-merge.sh4
-rwxr-xr-xgit-parse-remote.sh14
-rw-r--r--local-fetch.c33
-rw-r--r--pack-check.c8
-rw-r--r--pack-redundant.c30
-rw-r--r--pack.h30
-rw-r--r--sha1_file.c151
-rwxr-xr-xt/t3200-branch.sh6
-rwxr-xr-xt/t5300-pack-object.sh73
-rwxr-xr-xt/t5520-pull.sh24
-rw-r--r--tree-diff.c56
-rw-r--r--tree-walk.c4
-rw-r--r--tree-walk.h5
22 files changed, 380 insertions, 174 deletions
diff --git a/Documentation/RelNotes-1.5.0.5.txt b/Documentation/RelNotes-1.5.0.5.txt
new file mode 100644
index 0000000..aa86149
--- /dev/null
+++ b/Documentation/RelNotes-1.5.0.5.txt
@@ -0,0 +1,28 @@
+GIT v1.5.0.5 Release Notes
+==========================
+
+Fixes since v1.5.0.3
+--------------------
+
+* Bugfixes
+
+ - git-merge (hence git-pull) did not refuse fast-forwarding
+ when the working tree had local changes that would have
+ conflicted with it.
+
+ - git.el does not add duplicate sign-off lines.
+
+ - git-commit shows the full stat of the resulting commit, not
+ just about the files in the current directory, when run from
+ a subdirectory.
+
+ - "git-checkout -m '@{8 hours ago}'" had a funny failure from
+ eval; fixed.
+
+ - git-gui updates.
+
+* Documentation updates
+
+* User manual updates
+
+
diff --git a/Documentation/config.txt b/Documentation/config.txt
index aaae9ac..953acae 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -272,6 +272,10 @@ branch.<name>.merge::
`git fetch`) to lookup the default branch for merging. Without
this option, `git pull` defaults to merge the first refspec fetched.
Specify multiple values to get an octopus merge.
+ If you wish to setup `git pull` so that it merges into <name> from
+ another branch in the local repository, you can point
+ branch.<name>.merge to the desired branch, and use the special setting
+ `.` (a period) for branch.<name>.remote.
color.branch::
A boolean to enable/disable color in the output of
diff --git a/builtin-branch.c b/builtin-branch.c
index 42b1ff1..a4494ee 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -372,9 +372,26 @@ static int get_remote_config(const char *key, const char *value)
return 0;
}
-static void set_branch_defaults(const char *name, const char *real_ref)
+static void set_branch_merge(const char *name, const char *config_remote,
+ const char *config_repo)
{
char key[1024];
+ if (sizeof(key) <=
+ snprintf(key, sizeof(key), "branch.%s.remote", name))
+ die("what a long branch name you have!");
+ git_config_set(key, config_remote);
+
+ /*
+ * We do not have to check if we have enough space for
+ * the 'merge' key, since it's shorter than the
+ * previous 'remote' key, which we already checked.
+ */
+ snprintf(key, sizeof(key), "branch.%s.merge", name);
+ git_config_set(key, config_repo);
+}
+
+static void set_branch_defaults(const char *name, const char *real_ref)
+{
const char *slash = strrchr(real_ref, '/');
if (!slash)
@@ -384,21 +401,15 @@ static void set_branch_defaults(const char *name, const char *real_ref)
start_len = strlen(real_ref);
base_len = slash - real_ref;
git_config(get_remote_config);
+ if (!config_repo && !config_remote &&
+ !prefixcmp(real_ref, "refs/heads/")) {
+ set_branch_merge(name, ".", real_ref);
+ printf("Branch %s set up to track local branch %s.\n",
+ name, real_ref);
+ }
if (config_repo && config_remote) {
- if (sizeof(key) <=
- snprintf(key, sizeof(key), "branch.%s.remote", name))
- die("what a long branch name you have!");
- git_config_set(key, config_remote);
-
- /*
- * We do not have to check if we have enough space for
- * the 'merge' key, since it's shorter than the
- * previous 'remote' key, which we already checked.
- */
- snprintf(key, sizeof(key), "branch.%s.merge", name);
- git_config_set(key, config_repo);
-
+ set_branch_merge(name, config_remote, config_repo);
printf("Branch %s set up to track remote branch %s.\n",
name, real_ref);
}
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index f8ebad0..73d448b 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -166,11 +166,12 @@ static void prepare_pack_revindex(struct pack_revindex *rix)
struct packed_git *p = rix->p;
int num_ent = num_packed_objects(p);
int i;
- void *index = p->index_base + 256;
+ const char *index = p->index_data;
+ index += 4 * 256;
rix->revindex = xmalloc(sizeof(*rix->revindex) * (num_ent + 1));
for (i = 0; i < num_ent; i++) {
- unsigned int hl = *((unsigned int *)((char *) index + 24*i));
+ uint32_t hl = *((uint32_t *)(index + 24 * i));
rix->revindex[i].offset = ntohl(hl);
rix->revindex[i].nr = i;
}
@@ -217,11 +218,11 @@ static off_t find_packed_object_size(struct packed_git *p, off_t ofs)
return entry[1].offset - ofs;
}
-static unsigned char *find_packed_object_name(struct packed_git *p,
- off_t ofs)
+static const unsigned char *find_packed_object_name(struct packed_git *p,
+ off_t ofs)
{
struct revindex_entry *entry = find_packed_object(p, ofs);
- return (unsigned char *)(p->index_base + 256) + 24 * entry->nr + 4;
+ return ((unsigned char *)p->index_data) + 4 * 256 + 24 * entry->nr + 4;
}
static void *delta_against(void *buf, unsigned long size, struct object_entry *entry)
@@ -996,7 +997,8 @@ static void check_object(struct object_entry *entry)
* delta.
*/
if (!no_reuse_delta) {
- unsigned char c, *base_name;
+ unsigned char c;
+ const unsigned char *base_name;
off_t ofs;
unsigned long used_0;
/* there is at least 20 bytes left in the pack */
diff --git a/cache.h b/cache.h
index a4762ed..3818e10 100644
--- a/cache.h
+++ b/cache.h
@@ -371,10 +371,11 @@ struct pack_window {
extern struct packed_git {
struct packed_git *next;
struct pack_window *windows;
- uint32_t *index_base;
- time_t mtime;
+ const void *index_data;
off_t index_size;
off_t pack_size;
+ time_t mtime;
+ int index_version;
int pack_fd;
int pack_local;
unsigned char sha1[20];
@@ -412,7 +413,7 @@ extern int server_supports(const char *feature);
extern struct packed_git *parse_pack_index(unsigned char *sha1);
extern struct packed_git *parse_pack_index_file(const unsigned char *sha1,
- char *idx_path);
+ const char *idx_path);
extern void prepare_packed_git(void);
extern void reprepare_packed_git(void);
@@ -424,7 +425,7 @@ extern struct packed_git *find_sha1_pack(const unsigned char *sha1,
extern void pack_report(void);
extern unsigned char* use_pack(struct packed_git *, struct pack_window **, off_t, unsigned int *);
extern void unuse_pack(struct pack_window **);
-extern struct packed_git *add_packed_git(char *, int, int);
+extern struct packed_git *add_packed_git(const char *, int, int);
extern uint32_t num_packed_objects(const struct packed_git *p);
extern int nth_packed_object_sha1(const struct packed_git *, uint32_t, unsigned char*);
extern off_t find_pack_entry_one(const unsigned char *, struct packed_git *);
diff --git a/config.c b/config.c
index a3c7b77..d537311 100644
--- a/config.c
+++ b/config.c
@@ -351,12 +351,12 @@ int git_default_config(const char *var, const char *value)
}
if (!strcmp(var, "i18n.commitencoding")) {
- git_commit_encoding = strdup(value);
+ git_commit_encoding = xstrdup(value);
return 0;
}
if (!strcmp(var, "i18n.logoutputencoding")) {
- git_log_output_encoding = strdup(value);
+ git_log_output_encoding = xstrdup(value);
return 0;
}
diff --git a/git-applymbox.sh b/git-applymbox.sh
index 2cbdc7e..3efd6a7 100755
--- a/git-applymbox.sh
+++ b/git-applymbox.sh
@@ -77,9 +77,9 @@ do
*)
git-mailinfo $keep_subject $utf8 \
.dotest/msg .dotest/patch <$i >.dotest/info || exit 1
- test -s $dotest/patch || {
+ test -s .dotest/patch || {
echo "Patch is empty. Was is split wrong?"
- stop_here $this
+ exit 1
}
git-stripspace < .dotest/msg > .dotest/msg-clean
;;
diff --git a/git-checkout.sh b/git-checkout.sh
index fcadf20..39ffa8b 100755
--- a/git-checkout.sh
+++ b/git-checkout.sh
@@ -89,7 +89,7 @@ while [ "$#" != "0" ]; do
esac
done
-case "$new_branch,$track" in
+case "$newbranch,$track" in
,--*)
die "git checkout: --track and --no-track require -b"
esac
diff --git a/git-fetch.sh b/git-fetch.sh
index 9d45dd2..e218042 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -157,7 +157,7 @@ then
fi
fi
-fetch_native () {
+fetch_all_at_once () {
eval=$(echo "$1" | git-fetch--tool parse-reflist "-")
eval "$eval"
@@ -165,7 +165,9 @@ fetch_native () {
( : subshell because we muck with IFS
IFS=" $LF"
(
- if test -f "$remote" ; then
+ if test "$remote" = . ; then
+ git-show-ref $rref || echo failed "$remote"
+ elif test -f "$remote" ; then
test -n "$shallow_depth" &&
die "shallow clone with bundle is not supported"
git-bundle unbundle "$remote" $rref ||
@@ -188,7 +190,7 @@ fetch_native () {
}
-fetch_dumb () {
+fetch_per_ref () {
reflist="$1"
refs=
rref=
@@ -292,10 +294,10 @@ fetch_dumb () {
fetch_main () {
case "$remote" in
http://* | https://* | ftp://* | rsync://* )
- fetch_dumb "$@"
+ fetch_per_ref "$@"
;;
*)
- fetch_native "$@"
+ fetch_all_at_once "$@"
;;
esac
}
diff --git a/git-merge.sh b/git-merge.sh
index 6ce62c8..8759c5a 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -292,13 +292,13 @@ f,*)
# Again the most common case of merging one remote.
echo "Updating $(git-rev-parse --short $head)..$(git-rev-parse --short $1)"
git-update-index --refresh 2>/dev/null
- new_head=$(git-rev-parse --verify "$1^0") &&
- git-read-tree -v -m -u --exclude-per-directory=.gitignore $head "$new_head" &&
msg="Fast forward"
if test -n "$have_message"
then
msg="$msg (no commit created; -m option ignored)"
fi
+ new_head=$(git-rev-parse --verify "$1^0") &&
+ git-read-tree -v -m -u --exclude-per-directory=.gitignore $head "$new_head" &&
finish "$new_head" "$msg" || exit
dropsave
exit 0
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index c46131f..437b0c3 100755
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -9,6 +9,9 @@ get_data_source () {
*/*)
echo ''
;;
+ .)
+ echo self
+ ;;
*)
if test "$(git-config --get "remote.$1.url")"
then
@@ -31,6 +34,9 @@ get_remote_url () {
'')
echo "$1"
;;
+ self)
+ echo "$1"
+ ;;
config)
git-config --get "remote.$1.url"
;;
@@ -57,7 +63,7 @@ get_default_remote () {
get_remote_default_refs_for_push () {
data_source=$(get_data_source "$1")
case "$data_source" in
- '' | branches)
+ '' | branches | self)
;; # no default push mapping, just send matching refs.
config)
git-config --get-all "remote.$1.push" ;;
@@ -163,6 +169,10 @@ get_remote_default_refs_for_fetch () {
case "$data_source" in
'')
echo "HEAD:" ;;
+ self)
+ canon_refs_list_for_fetch -d "$1" \
+ $(git-for-each-ref --format='%(refname):')
+ ;;
config)
canon_refs_list_for_fetch -d "$1" \
$(git-config --get-all "remote.$1.fetch") ;;
@@ -177,7 +187,7 @@ get_remote_default_refs_for_fetch () {
}' "$GIT_DIR/remotes/$1")
;;
*)
- die "internal error: get-remote-default-ref-for-push $1" ;;
+ die "internal error: get-remote-default-ref-for-fetch $1" ;;
esac
}
diff --git a/local-fetch.c b/local-fetch.c
index 7cfe8b3..4b650ef 100644
--- a/local-fetch.c
+++ b/local-fetch.c
@@ -64,9 +64,9 @@ static int copy_file(const char *source, char *dest, const char *hex,
}
/* If we got ENOENT there is no point continuing. */
if (errno == ENOENT) {
- if (warn_if_not_exists)
- fprintf(stderr, "does not exist %s\n", source);
- return -1;
+ if (!warn_if_not_exists)
+ return -1;
+ return error("does not exist %s", source);
}
}
if (use_symlink) {
@@ -74,9 +74,8 @@ static int copy_file(const char *source, char *dest, const char *hex,
if (stat(source, &st)) {
if (!warn_if_not_exists && errno == ENOENT)
return -1;
- fprintf(stderr, "cannot stat %s: %s\n", source,
- strerror(errno));
- return -1;
+ return error("cannot stat %s: %s", source,
+ strerror(errno));
}
if (!symlink(source, dest)) {
pull_say("symlink %s\n", hex);
@@ -90,25 +89,21 @@ static int copy_file(const char *source, char *dest, const char *hex,
if (ifd < 0) {
if (!warn_if_not_exists && errno == ENOENT)
return -1;
- fprintf(stderr, "cannot open %s\n", source);
- return -1;
+ return error("cannot open %s", source);
}
ofd = open(dest, O_WRONLY | O_CREAT | O_EXCL, 0666);
if (ofd < 0) {
- fprintf(stderr, "cannot open %s\n", dest);
close(ifd);
- return -1;
+ return error("cannot open %s", dest);
}
status = copy_fd(ifd, ofd);
close(ofd);
if (status)
- fprintf(stderr, "cannot write %s\n", dest);
- else
- pull_say("copy %s\n", hex);
- return status;
+ return error("cannot write %s", dest);
+ pull_say("copy %s\n", hex);
+ return 0;
}
- fprintf(stderr, "failed to copy %s with given copy methods.\n", hex);
- return -1;
+ return error("failed to copy %s with given copy methods.", hex);
}
static int fetch_pack(const unsigned char *sha1)
@@ -181,13 +176,11 @@ int fetch_ref(char *ref, unsigned char *sha1)
ifd = open(filename, O_RDONLY);
if (ifd < 0) {
close(ifd);
- fprintf(stderr, "cannot open %s\n", filename);
- return -1;
+ return error("cannot open %s", filename);
}
if (read_in_full(ifd, hex, 40) != 40 || get_sha1_hex(hex, sha1)) {
close(ifd);
- fprintf(stderr, "cannot read from %s\n", filename);
- return -1;
+ return error("cannot read from %s", filename);
}
close(ifd);
pull_say("ref %s\n", sha1_to_hex(sha1));
diff --git a/pack-check.c b/pack-check.c
index 299c514..d988322 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -5,7 +5,7 @@ static int verify_packfile(struct packed_git *p,
struct pack_window **w_curs)
{
off_t index_size = p->index_size;
- void *index_base = p->index_base;
+ const unsigned char *index_base = p->index_data;
SHA_CTX ctx;
unsigned char sha1[20];
off_t offset = 0, pack_sig = p->pack_size - 20;
@@ -31,7 +31,7 @@ static int verify_packfile(struct packed_git *p,
if (hashcmp(sha1, use_pack(p, w_curs, pack_sig, NULL)))
return error("Packfile %s SHA1 mismatch with itself",
p->pack_name);
- if (hashcmp(sha1, (unsigned char *)index_base + index_size - 40))
+ if (hashcmp(sha1, index_base + index_size - 40))
return error("Packfile %s SHA1 mismatch with idx",
p->pack_name);
unuse_pack(w_curs);
@@ -127,7 +127,7 @@ static void show_pack_info(struct packed_git *p)
int verify_pack(struct packed_git *p, int verbose)
{
off_t index_size = p->index_size;
- void *index_base = p->index_base;
+ const unsigned char *index_base = p->index_data;
SHA_CTX ctx;
unsigned char sha1[20];
int ret;
@@ -137,7 +137,7 @@ int verify_pack(struct packed_git *p, int verbose)
SHA1_Init(&ctx);
SHA1_Update(&ctx, index_base, (unsigned int)(index_size - 20));
SHA1_Final(sha1, &ctx);
- if (hashcmp(sha1, (unsigned char *)index_base + index_size - 20))
+ if (hashcmp(sha1, index_base + index_size - 20))
ret = error("Packfile index for %s SHA1 mismatch",
p->pack_name);
diff --git a/pack-redundant.c b/pack-redundant.c
index c8f7d9a..40e579b 100644
--- a/pack-redundant.c
+++ b/pack-redundant.c
@@ -17,7 +17,7 @@ static int load_all_packs, verbose, alt_odb;
struct llist_item {
struct llist_item *next;
- unsigned char *sha1;
+ const unsigned char *sha1;
};
static struct llist {
struct llist_item *front;
@@ -104,9 +104,9 @@ static struct llist * llist_copy(struct llist *list)
return ret;
}
-static inline struct llist_item * llist_insert(struct llist *list,
- struct llist_item *after,
- unsigned char *sha1)
+static inline struct llist_item *llist_insert(struct llist *list,
+ struct llist_item *after,
+ const unsigned char *sha1)
{
struct llist_item *new = llist_item_get();
new->sha1 = sha1;
@@ -128,12 +128,14 @@ static inline struct llist_item * llist_insert(struct llist *list,
return new;
}
-static inline struct llist_item *llist_insert_back(struct llist *list, unsigned char *sha1)
+static inline struct llist_item *llist_insert_back(struct llist *list,
+ const unsigned char *sha1)
{
return llist_insert(list, list->back, sha1);
}
-static inline struct llist_item *llist_insert_sorted_unique(struct llist *list, unsigned char *sha1, struct llist_item *hint)
+static inline struct llist_item *llist_insert_sorted_unique(struct llist *list,
+ const unsigned char *sha1, struct llist_item *hint)
{
struct llist_item *prev = NULL, *l;
@@ -246,12 +248,12 @@ static struct pack_list * pack_list_difference(const struct pack_list *A,
static void cmp_two_packs(struct pack_list *p1, struct pack_list *p2)
{
int p1_off, p2_off;
- unsigned char *p1_base, *p2_base;
+ const unsigned char *p1_base, *p2_base;
struct llist_item *p1_hint = NULL, *p2_hint = NULL;
p1_off = p2_off = 256 * 4 + 4;
- p1_base = (unsigned char *) p1->pack->index_base;
- p2_base = (unsigned char *) p2->pack->index_base;
+ p1_base = p1->pack->index_data;
+ p2_base = p2->pack->index_data;
while (p1_off <= p1->pack->index_size - 3 * 20 &&
p2_off <= p2->pack->index_size - 3 * 20)
@@ -351,11 +353,11 @@ static size_t sizeof_union(struct packed_git *p1, struct packed_git *p2)
{
size_t ret = 0;
int p1_off, p2_off;
- unsigned char *p1_base, *p2_base;
+ const unsigned char *p1_base, *p2_base;
p1_off = p2_off = 256 * 4 + 4;
- p1_base = (unsigned char *)p1->index_base;
- p2_base = (unsigned char *)p2->index_base;
+ p1_base = p1->index_data;
+ p2_base = p2->index_data;
while (p1_off <= p1->index_size - 3 * 20 &&
p2_off <= p2->index_size - 3 * 20)
@@ -534,7 +536,7 @@ static struct pack_list * add_pack(struct packed_git *p)
{
struct pack_list l;
size_t off;
- unsigned char *base;
+ const unsigned char *base;
if (!p->pack_local && !(alt_odb || verbose))
return NULL;
@@ -543,7 +545,7 @@ static struct pack_list * add_pack(struct packed_git *p)
llist_init(&l.all_objects);
off = 256 * 4 + 4;
- base = (unsigned char *)p->index_base;
+ base = p->index_data;
while (off <= p->index_size - 3 * 20) {
llist_insert_back(l.all_objects, base + off);
off += 24;
diff --git a/pack.h b/pack.h
index deb427e..d4d412c 100644
--- a/pack.h
+++ b/pack.h
@@ -16,24 +16,15 @@ struct pack_header {
};
/*
- * Packed object index header
- *
- * struct pack_idx_header {
- * uint32_t idx_signature;
- * uint32_t idx_version;
- * };
- *
- * Note: this header isn't active yet. In future versions of git
- * we may change the index file format. At that time we would start
- * the first four bytes of the new index format with this signature,
- * as all older git binaries would find this value illegal and abort
- * reading the file.
+ * The first four bytes of index formats later than version 1 should
+ * start with this signature, as all older git binaries would find this
+ * value illegal and abort reading the file.
*
* This is the case because the number of objects in a packfile
* cannot exceed 1,431,660,000 as every object would need at least
- * 3 bytes of data and the overall packfile cannot exceed 4 GiB due
- * to the 32 bit offsets used by the index. Clearly the signature
- * exceeds this maximum.
+ * 3 bytes of data and the overall packfile cannot exceed 4 GiB with
+ * version 1 of the index file due to the offsets limited to 32 bits.
+ * Clearly the signature exceeds this maximum.
*
* Very old git binaries will also compare the first 4 bytes to the
* next 4 bytes in the index and abort with a "non-monotonic index"
@@ -43,6 +34,15 @@ struct pack_header {
*/
#define PACK_IDX_SIGNATURE 0xff744f63 /* "\377tOc" */
+/*
+ * Packed object index header
+ */
+struct pack_idx_header {
+ uint32_t idx_signature;
+ uint32_t idx_version;
+};
+
+
extern int verify_pack(struct packed_git *, int);
#define PH_ERROR_EOF (-1)
diff --git a/sha1_file.c b/sha1_file.c
index 5691448..ee64865 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -432,16 +432,15 @@ void pack_report()
pack_mapped, peak_pack_mapped);
}
-static int check_packed_git_idx(const char *path,
- unsigned long *idx_size_,
- void **idx_map_)
+static int check_packed_git_idx(const char *path, struct packed_git *p)
{
void *idx_map;
- uint32_t *index;
+ struct pack_idx_header *hdr;
size_t idx_size;
- uint32_t nr, i;
+ uint32_t nr, i, *index;
int fd = open(path, O_RDONLY);
struct stat st;
+
if (fd < 0)
return -1;
if (fstat(fd, &st)) {
@@ -456,15 +455,12 @@ static int check_packed_git_idx(const char *path,
idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
- index = idx_map;
- *idx_map_ = idx_map;
- *idx_size_ = idx_size;
-
/* a future index format would start with this, as older git
* binaries would fail the non-monotonic index check below.
* give a nicer warning to the user if we can.
*/
- if (index[0] == htonl(PACK_IDX_SIGNATURE)) {
+ hdr = idx_map;
+ if (hdr->idx_signature == htonl(PACK_IDX_SIGNATURE)) {
munmap(idx_map, idx_size);
return error("index file %s is a newer version"
" and is not supported by this binary"
@@ -473,6 +469,7 @@ static int check_packed_git_idx(const char *path,
}
nr = 0;
+ index = idx_map;
for (i = 0; i < 256; i++) {
uint32_t n = ntohl(index[i]);
if (n < nr) {
@@ -494,6 +491,9 @@ static int check_packed_git_idx(const char *path,
return error("wrong index file size in %s", path);
}
+ p->index_version = 1;
+ p->index_data = idx_map;
+ p->index_size = idx_size;
return 0;
}
@@ -614,7 +614,7 @@ static int open_packed_git_1(struct packed_git *p)
return error("end of packfile %s is unavailable", p->pack_name);
if (read_in_full(p->pack_fd, sha1, sizeof(sha1)) != sizeof(sha1))
return error("packfile %s signature is unavailable", p->pack_name);
- idx_sha1 = ((unsigned char *)p->index_base) + p->index_size - 40;
+ idx_sha1 = ((unsigned char *)p->index_data) + p->index_size - 40;
if (hashcmp(sha1, idx_sha1))
return error("packfile %s does not match index", p->pack_name);
return 0;
@@ -710,38 +710,37 @@ unsigned char* use_pack(struct packed_git *p,
return win->base + offset;
}
-struct packed_git *add_packed_git(char *path, int path_len, int local)
+struct packed_git *add_packed_git(const char *path, int path_len, int local)
{
struct stat st;
- struct packed_git *p;
- unsigned long idx_size;
- void *idx_map;
- unsigned char sha1[20];
+ struct packed_git *p = xmalloc(sizeof(*p) + path_len + 2);
- if (check_packed_git_idx(path, &idx_size, &idx_map))
+ /*
+ * Make sure a corresponding .pack file exists and that
+ * the index looks sane.
+ */
+ path_len -= strlen(".idx");
+ if (path_len < 1)
return NULL;
-
- /* do we have a corresponding .pack file? */
- strcpy(path + path_len - 4, ".pack");
- if (stat(path, &st) || !S_ISREG(st.st_mode)) {
- munmap(idx_map, idx_size);
+ memcpy(p->pack_name, path, path_len);
+ strcpy(p->pack_name + path_len, ".pack");
+ if (stat(p->pack_name, &st) || !S_ISREG(st.st_mode) ||
+ check_packed_git_idx(path, p)) {
+ free(p);
return NULL;
}
+
/* ok, it looks sane as far as we can check without
* actually mapping the pack file.
*/
- p = xmalloc(sizeof(*p) + path_len + 2);
- strcpy(p->pack_name, path);
- p->index_size = idx_size;
p->pack_size = st.st_size;
- p->index_base = idx_map;
p->next = NULL;
p->windows = NULL;
p->pack_fd = -1;
p->pack_local = local;
p->mtime = st.st_mtime;
- if ((path_len > 44) && !get_sha1_hex(path + path_len - 44, sha1))
- hashcpy(p->sha1, sha1);
+ if (path_len < 40 || get_sha1_hex(path + path_len - 40, p->sha1))
+ hashclr(p->sha1);
return p;
}
@@ -751,23 +750,19 @@ struct packed_git *parse_pack_index(unsigned char *sha1)
return parse_pack_index_file(sha1, path);
}
-struct packed_git *parse_pack_index_file(const unsigned char *sha1, char *idx_path)
+struct packed_git *parse_pack_index_file(const unsigned char *sha1,
+ const char *idx_path)
{
- struct packed_git *p;
- unsigned long idx_size;
- void *idx_map;
- char *path;
+ const char *path = sha1_pack_name(sha1);
+ struct packed_git *p = xmalloc(sizeof(*p) + strlen(path) + 2);
- if (check_packed_git_idx(idx_path, &idx_size, &idx_map))
+ if (check_packed_git_idx(idx_path, p)) {
+ free(p);
return NULL;
+ }
- path = sha1_pack_name(sha1);
-
- p = xmalloc(sizeof(*p) + strlen(path) + 2);
strcpy(p->pack_name, path);
- p->index_size = idx_size;
p->pack_size = 0;
- p->index_base = idx_map;
p->next = NULL;
p->windows = NULL;
p->pack_fd = -1;
@@ -1357,6 +1352,65 @@ static void *unpack_compressed_entry(struct packed_git *p,
return buffer;
}
+#define MAX_DELTA_CACHE (256)
+
+static struct delta_base_cache_entry {
+ struct packed_git *p;
+ off_t base_offset;
+ unsigned long size;
+ void *data;
+ enum object_type type;
+} delta_base_cache[MAX_DELTA_CACHE];
+
+static unsigned long pack_entry_hash(struct packed_git *p, off_t base_offset)
+{
+ unsigned long hash;
+
+ hash = (unsigned long)p + (unsigned long)base_offset;
+ hash += (hash >> 8) + (hash >> 16);
+ return hash & 0xff;
+}
+
+static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset,
+ unsigned long *base_size, enum object_type *type, int keep_cache)
+{
+ void *ret;
+ unsigned long hash = pack_entry_hash(p, base_offset);
+ struct delta_base_cache_entry *ent = delta_base_cache + hash;
+
+ ret = ent->data;
+ if (ret && ent->p == p && ent->base_offset == base_offset)
+ goto found_cache_entry;
+ return unpack_entry(p, base_offset, type, base_size);
+
+found_cache_entry:
+ if (!keep_cache)
+ ent->data = NULL;
+ else {
+ ret = xmalloc(ent->size + 1);
+ memcpy(ret, ent->data, ent->size);
+ ((char *)ret)[ent->size] = 0;
+ }
+ *type = ent->type;
+ *base_size = ent->size;
+ return ret;
+}
+
+static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
+ void *base, unsigned long base_size, enum object_type type)
+{
+ unsigned long hash = pack_entry_hash(p, base_offset);
+ struct delta_base_cache_entry *ent = delta_base_cache + hash;
+
+ if (ent->data)
+ free(ent->data);
+ ent->p = p;
+ ent->base_offset = base_offset;
+ ent->type = type;
+ ent->data = base;
+ ent->size = base_size;
+}
+
static void *unpack_delta_entry(struct packed_git *p,
struct pack_window **w_curs,
off_t curpos,
@@ -1370,7 +1424,7 @@ static void *unpack_delta_entry(struct packed_git *p,
off_t base_offset;
base_offset = get_delta_base(p, w_curs, &curpos, *type, obj_offset);
- base = unpack_entry(p, base_offset, type, &base_size);
+ base = cache_or_unpack_entry(p, base_offset, &base_size, type, 0);
if (!base)
die("failed to read delta base object"
" at %"PRIuMAX" from %s",
@@ -1383,7 +1437,7 @@ static void *unpack_delta_entry(struct packed_git *p,
if (!result)
die("failed to apply delta");
free(delta_data);
- free(base);
+ add_delta_base_cache(p, base_offset, base, base_size, *type);
return result;
}
@@ -1423,24 +1477,27 @@ uint32_t num_packed_objects(const struct packed_git *p)
int nth_packed_object_sha1(const struct packed_git *p, uint32_t n,
unsigned char* sha1)
{
- void *index = p->index_base + 256;
+ const unsigned char *index = p->index_data;
+ index += 4 * 256;
if (num_packed_objects(p) <= n)
return -1;
- hashcpy(sha1, (unsigned char *) index + (24 * n) + 4);
+ hashcpy(sha1, index + 24 * n + 4);
return 0;
}
off_t find_pack_entry_one(const unsigned char *sha1,
struct packed_git *p)
{
- uint32_t *level1_ofs = p->index_base;
+ const uint32_t *level1_ofs = p->index_data;
int hi = ntohl(level1_ofs[*sha1]);
int lo = ((*sha1 == 0x0) ? 0 : ntohl(level1_ofs[*sha1 - 1]));
- void *index = p->index_base + 256;
+ const unsigned char *index = p->index_data;
+
+ index += 4 * 256;
do {
int mi = (lo + hi) / 2;
- int cmp = hashcmp((unsigned char *)index + (24 * mi) + 4, sha1);
+ int cmp = hashcmp(index + 24 * mi + 4, sha1);
if (!cmp)
return ntohl(*((uint32_t *)((char *)index + (24 * mi))));
if (cmp > 0)
@@ -1564,7 +1621,7 @@ static void *read_packed_sha1(const unsigned char *sha1,
if (!find_pack_entry(sha1, &e, NULL))
return NULL;
else
- return unpack_entry(e.p, e.offset, type, size);
+ return cache_or_unpack_entry(e.p, e.offset, size, type, 1);
}
/*
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 75c000a..9558bdb 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -145,9 +145,15 @@ test_expect_success 'test overriding tracking setup via --no-track' \
git-config remote.local.fetch refs/heads/*:refs/remotes/local/* &&
(git-show-ref -q refs/remotes/local/master || git-fetch local) &&
git-branch --no-track my2 local/master &&
+ git-config branch.autosetupmerge false &&
! test $(git-config branch.my2.remote) = local &&
! test $(git-config branch.my2.merge) = refs/heads/master'
+test_expect_success 'test local tracking setup' \
+ 'git branch --track my6 s &&
+ test $(git-config branch.my6.remote) = . &&
+ test $(git-config branch.my6.merge) = refs/heads/s'
+
# Keep this test last, as it changes the current branch
cat >expect <<EOF
0000000000000000000000000000000000000000 $HEAD $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> 1117150200 +0000 branch: Created from master
diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh
index f511547..eacb1e9 100755
--- a/t/t5300-pack-object.sh
+++ b/t/t5300-pack-object.sh
@@ -64,7 +64,7 @@ test_expect_success \
cd "$TRASH"
test_expect_success \
- 'pack with delta' \
+ 'pack with REF_DELTA' \
'pwd &&
packname_2=$(git-pack-objects test-2 <obj-list)'
@@ -72,7 +72,7 @@ rm -fr .git2
mkdir .git2
test_expect_success \
- 'unpack with delta' \
+ 'unpack with REF_DELTA' \
'GIT_OBJECT_DIRECTORY=.git2/objects &&
export GIT_OBJECT_DIRECTORY &&
git-init &&
@@ -82,7 +82,7 @@ test_expect_success \
unset GIT_OBJECT_DIRECTORY
cd "$TRASH/.git2"
test_expect_success \
- 'check unpack with delta' \
+ 'check unpack with REF_DELTA' \
'(cd ../.git && find objects -type f -print) |
while read path
do
@@ -93,6 +93,42 @@ test_expect_success \
done'
cd "$TRASH"
+test_expect_success \
+ 'pack with OFS_DELTA' \
+ 'pwd &&
+ packname_3=$(git-pack-objects --delta-base-offset test-3 <obj-list)'
+
+rm -fr .git2
+mkdir .git2
+
+test_expect_success \
+ 'unpack with OFS_DELTA' \
+ 'GIT_OBJECT_DIRECTORY=.git2/objects &&
+ export GIT_OBJECT_DIRECTORY &&
+ git-init &&
+ git-unpack-objects -n <test-3-${packname_3}.pack &&
+ git-unpack-objects <test-3-${packname_3}.pack'
+
+unset GIT_OBJECT_DIRECTORY
+cd "$TRASH/.git2"
+test_expect_success \
+ 'check unpack with OFS_DELTA' \
+ '(cd ../.git && find objects -type f -print) |
+ while read path
+ do
+ cmp $path ../.git/$path || {
+ echo $path differs.
+ return 1
+ }
+ done'
+cd "$TRASH"
+
+test_expect_success \
+ 'compare delta flavors' \
+ 'size_2=`stat -c "%s" test-2-${packname_2}.pack` &&
+ size_3=`stat -c "%s" test-3-${packname_3}.pack` &&
+ test $size_2 -gt $size_3'
+
rm -fr .git2
mkdir .git2
@@ -111,12 +147,11 @@ test_expect_success \
} >current &&
diff expect current'
-
test_expect_success \
- 'use packed deltified objects' \
+ 'use packed deltified (REF_DELTA) objects' \
'GIT_OBJECT_DIRECTORY=.git2/objects &&
export GIT_OBJECT_DIRECTORY &&
- rm -f .git2/objects/pack/test-?.idx &&
+ rm .git2/objects/pack/test-* &&
cp test-2-${packname_2}.pack test-2-${packname_2}.idx .git2/objects/pack && {
git-diff-tree --root -p $commit &&
while read object
@@ -127,11 +162,28 @@ test_expect_success \
} >current &&
diff expect current'
+test_expect_success \
+ 'use packed deltified (OFS_DELTA) objects' \
+ 'GIT_OBJECT_DIRECTORY=.git2/objects &&
+ export GIT_OBJECT_DIRECTORY &&
+ rm .git2/objects/pack/test-* &&
+ cp test-3-${packname_3}.pack test-3-${packname_3}.idx .git2/objects/pack && {
+ git-diff-tree --root -p $commit &&
+ while read object
+ do
+ t=`git-cat-file -t $object` &&
+ git-cat-file $t $object || return 1
+ done <obj-list
+ } >current &&
+ diff expect current'
+
unset GIT_OBJECT_DIRECTORY
test_expect_success \
'verify pack' \
- 'git-verify-pack test-1-${packname_1}.idx test-2-${packname_2}.idx'
+ 'git-verify-pack test-1-${packname_1}.idx \
+ test-2-${packname_2}.idx \
+ test-3-${packname_3}.idx'
test_expect_success \
'corrupt a pack and see if verify catches' \
@@ -194,6 +246,13 @@ test_expect_success \
git-index-pack test-3.pack &&
cmp test-3.idx test-2-${packname_2}.idx &&
+ cp test-3-${packname_3}.pack test-3.pack &&
+ git-index-pack -o tmp.idx test-3-${packname_3}.pack &&
+ cmp tmp.idx test-3-${packname_3}.idx &&
+
+ git-index-pack test-3.pack &&
+ cmp test-3.idx test-3-${packname_3}.idx &&
+
:'
test_done
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 7eb3783..243212d 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -29,5 +29,29 @@ test_expect_success 'checking the results' '
diff file cloned/file
'
+test_expect_success 'test . as a remote' '
+
+ git branch copy master &&
+ git config branch.copy.remote . &&
+ git config branch.copy.merge refs/heads/master &&
+ echo updated >file &&
+ git commit -a -m updated &&
+ git checkout copy &&
+ test `cat file` = file &&
+ git pull &&
+ test `cat file` = updated
+'
+
+test_expect_success 'the default remote . should not break explicit pull' '
+ git checkout -b second master^ &&
+ echo modified >file &&
+ git commit -a -m modified &&
+ git checkout copy &&
+ git reset --hard HEAD^ &&
+ test `cat file` = file &&
+ git pull . second &&
+ test `cat file` = modified
+'
+
test_done
diff --git a/tree-diff.c b/tree-diff.c
index 44cde74..3940962 100644
--- a/tree-diff.c
+++ b/tree-diff.c
@@ -5,9 +5,8 @@
#include "diff.h"
#include "tree.h"
-static char *malloc_base(const char *base, const char *path, int pathlen)
+static char *malloc_base(const char *base, int baselen, const char *path, int pathlen)
{
- int baselen = strlen(base);
char *newbase = xmalloc(baselen + pathlen + 2);
memcpy(newbase, base, baselen);
memcpy(newbase + baselen, path, pathlen);
@@ -16,9 +15,9 @@ static char *malloc_base(const char *base, const char *path, int pathlen)
}
static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc,
- const char *base);
+ const char *base, int baselen);
-static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)
+static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const char *base, int baselen, struct diff_options *opt)
{
unsigned mode1, mode2;
const char *path1, *path2;
@@ -28,15 +27,15 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
sha1 = tree_entry_extract(t1, &path1, &mode1);
sha2 = tree_entry_extract(t2, &path2, &mode2);
- pathlen1 = strlen(path1);
- pathlen2 = strlen(path2);
+ pathlen1 = tree_entry_len(path1, sha1);
+ pathlen2 = tree_entry_len(path2, sha2);
cmp = base_name_compare(path1, pathlen1, mode1, path2, pathlen2, mode2);
if (cmp < 0) {
- show_entry(opt, "-", t1, base);
+ show_entry(opt, "-", t1, base, baselen);
return -1;
}
if (cmp > 0) {
- show_entry(opt, "+", t2, base);
+ show_entry(opt, "+", t2, base, baselen);
return 1;
}
if (!opt->find_copies_harder && !hashcmp(sha1, sha2) && mode1 == mode2)
@@ -47,14 +46,14 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
* file, we need to consider it a remove and an add.
*/
if (S_ISDIR(mode1) != S_ISDIR(mode2)) {
- show_entry(opt, "-", t1, base);
- show_entry(opt, "+", t2, base);
+ show_entry(opt, "-", t1, base, baselen);
+ show_entry(opt, "+", t2, base, baselen);
return 0;
}
if (opt->recursive && S_ISDIR(mode1)) {
int retval;
- char *newbase = malloc_base(base, path1, pathlen1);
+ char *newbase = malloc_base(base, baselen, path1, pathlen1);
if (opt->tree_in_recursive)
opt->change(opt, mode1, mode2,
sha1, sha2, base, path1);
@@ -67,20 +66,20 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const
return 0;
}
-static int interesting(struct tree_desc *desc, const char *base, struct diff_options *opt)
+static int interesting(struct tree_desc *desc, const char *base, int baselen, struct diff_options *opt)
{
const char *path;
+ const unsigned char *sha1;
unsigned mode;
int i;
- int baselen, pathlen;
+ int pathlen;
if (!opt->nr_paths)
return 1;
- (void)tree_entry_extract(desc, &path, &mode);
+ sha1 = tree_entry_extract(desc, &path, &mode);
- pathlen = strlen(path);
- baselen = strlen(base);
+ pathlen = tree_entry_len(path, sha1);
for (i=0; i < opt->nr_paths; i++) {
const char *match = opt->paths[i];
@@ -121,18 +120,18 @@ static int interesting(struct tree_desc *desc, const char *base, struct diff_opt
}
/* A whole sub-tree went away or appeared */
-static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base)
+static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen)
{
while (desc->size) {
- if (interesting(desc, base, opt))
- show_entry(opt, prefix, desc, base);
+ if (interesting(desc, base, baselen, opt))
+ show_entry(opt, prefix, desc, base, baselen);
update_tree_entry(desc);
}
}
/* A file entry went away or appeared */
static void show_entry(struct diff_options *opt, const char *prefix, struct tree_desc *desc,
- const char *base)
+ const char *base, int baselen)
{
unsigned mode;
const char *path;
@@ -140,7 +139,8 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
if (opt->recursive && S_ISDIR(mode)) {
enum object_type type;
- char *newbase = malloc_base(base, path, strlen(path));
+ int pathlen = tree_entry_len(path, sha1);
+ char *newbase = malloc_base(base, baselen, path, pathlen);
struct tree_desc inner;
void *tree;
@@ -149,7 +149,7 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
die("corrupt tree sha %s", sha1_to_hex(sha1));
inner.buf = tree;
- show_tree(opt, prefix, &inner, newbase);
+ show_tree(opt, prefix, &inner, newbase, baselen + 1 + pathlen);
free(tree);
free(newbase);
@@ -160,28 +160,30 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree
int diff_tree(struct tree_desc *t1, struct tree_desc *t2, const char *base, struct diff_options *opt)
{
+ int baselen = strlen(base);
+
while (t1->size | t2->size) {
if (opt->quiet && opt->has_changes)
break;
- if (opt->nr_paths && t1->size && !interesting(t1, base, opt)) {
+ if (opt->nr_paths && t1->size && !interesting(t1, base, baselen, opt)) {
update_tree_entry(t1);
continue;
}
- if (opt->nr_paths && t2->size && !interesting(t2, base, opt)) {
+ if (opt->nr_paths && t2->size && !interesting(t2, base, baselen, opt)) {
update_tree_entry(t2);
continue;
}
if (!t1->size) {
- show_entry(opt, "+", t2, base);
+ show_entry(opt, "+", t2, base, baselen);
update_tree_entry(t2);
continue;
}
if (!t2->size) {
- show_entry(opt, "-", t1, base);
+ show_entry(opt, "-", t1, base, baselen);
update_tree_entry(t1);
continue;
}
- switch (compare_tree_entry(t1, t2, base, opt)) {
+ switch (compare_tree_entry(t1, t2, base, baselen, opt)) {
case -1:
update_tree_entry(t1);
continue;
diff --git a/tree-walk.c b/tree-walk.c
index 70f8999..a4a4e2a 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -32,7 +32,7 @@ static void entry_clear(struct name_entry *a)
static void entry_extract(struct tree_desc *t, struct name_entry *a)
{
a->sha1 = tree_entry_extract(t, &a->path, &a->mode);
- a->pathlen = strlen(a->path);
+ a->pathlen = tree_entry_len(a->path, a->sha1);
}
void update_tree_entry(struct tree_desc *desc)
@@ -169,7 +169,7 @@ static int find_tree_entry(struct tree_desc *t, const char *name, unsigned char
sha1 = tree_entry_extract(t, &entry, mode);
update_tree_entry(t);
- entrylen = strlen(entry);
+ entrylen = tree_entry_len(entry, sha1);
if (entrylen > namelen)
continue;
cmp = memcmp(name, entry, entrylen);
diff --git a/tree-walk.h b/tree-walk.h
index e57befa..a0d7afd 100644
--- a/tree-walk.h
+++ b/tree-walk.h
@@ -13,6 +13,11 @@ struct name_entry {
int pathlen;
};
+static inline int tree_entry_len(const char *name, const unsigned char *sha1)
+{
+ return (char *)sha1 - (char *)name - 1;
+}
+
void update_tree_entry(struct tree_desc *);
const unsigned char *tree_entry_extract(struct tree_desc *, const char **, unsigned int *);