зеркало из https://github.com/microsoft/git.git
Merge branch 'master' into js/merge-base
This is to pull in the object-hash clean-up from the master branch.
This commit is contained in:
Коммит
f23c75a8ec
|
@ -15,9 +15,9 @@ SYNOPSIS
|
|||
DESCRIPTION
|
||||
-----------
|
||||
Updates the index file for given paths, or all modified files if
|
||||
'-a' is specified, and makes a commit object. The command
|
||||
VISUAL and EDITOR environment variables to edit the commit log
|
||||
message.
|
||||
'-a' is specified, and makes a commit object. The command specified
|
||||
by either the VISUAL or EDITOR environment variables are used to edit
|
||||
the commit log message.
|
||||
|
||||
Several environment variable are used during commits. They are
|
||||
documented in gitlink:git-commit-tree[1].
|
||||
|
|
4
Makefile
4
Makefile
|
@ -587,11 +587,11 @@ git-ssh-push$X: rsh.o
|
|||
git-imap-send$X: imap-send.o $(LIB_FILE)
|
||||
|
||||
http.o http-fetch.o http-push.o: http.h
|
||||
git-http-fetch$X: fetch.o http.o http-fetch.o $(LIB_FILE)
|
||||
git-http-fetch$X: fetch.o http.o http-fetch.o $(GITLIBS)
|
||||
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
|
||||
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
|
||||
|
||||
git-http-push$X: revision.o http.o http-push.o $(LIB_FILE)
|
||||
git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
|
||||
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
|
||||
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
|
||||
|
||||
|
|
18
connect.c
18
connect.c
|
@ -328,7 +328,7 @@ static enum protocol get_protocol(const char *name)
|
|||
*/
|
||||
static int git_tcp_connect_sock(char *host)
|
||||
{
|
||||
int sockfd = -1;
|
||||
int sockfd = -1, saved_errno = 0;
|
||||
char *colon, *end;
|
||||
const char *port = STR(DEFAULT_GIT_PORT);
|
||||
struct addrinfo hints, *ai0, *ai;
|
||||
|
@ -362,9 +362,12 @@ static int git_tcp_connect_sock(char *host)
|
|||
for (ai0 = ai; ai; ai = ai->ai_next) {
|
||||
sockfd = socket(ai->ai_family,
|
||||
ai->ai_socktype, ai->ai_protocol);
|
||||
if (sockfd < 0)
|
||||
if (sockfd < 0) {
|
||||
saved_errno = errno;
|
||||
continue;
|
||||
}
|
||||
if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
|
||||
saved_errno = errno;
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
continue;
|
||||
|
@ -375,7 +378,7 @@ static int git_tcp_connect_sock(char *host)
|
|||
freeaddrinfo(ai0);
|
||||
|
||||
if (sockfd < 0)
|
||||
die("unable to connect a socket (%s)", strerror(errno));
|
||||
die("unable to connect a socket (%s)", strerror(saved_errno));
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
@ -387,7 +390,7 @@ static int git_tcp_connect_sock(char *host)
|
|||
*/
|
||||
static int git_tcp_connect_sock(char *host)
|
||||
{
|
||||
int sockfd = -1;
|
||||
int sockfd = -1, saved_errno = 0;
|
||||
char *colon, *end;
|
||||
char *port = STR(DEFAULT_GIT_PORT), *ep;
|
||||
struct hostent *he;
|
||||
|
@ -426,8 +429,10 @@ static int git_tcp_connect_sock(char *host)
|
|||
|
||||
for (ap = he->h_addr_list; *ap; ap++) {
|
||||
sockfd = socket(he->h_addrtype, SOCK_STREAM, 0);
|
||||
if (sockfd < 0)
|
||||
if (sockfd < 0) {
|
||||
saved_errno = errno;
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&sa, 0, sizeof sa);
|
||||
sa.sin_family = he->h_addrtype;
|
||||
|
@ -435,6 +440,7 @@ static int git_tcp_connect_sock(char *host)
|
|||
memcpy(&sa.sin_addr, *ap, he->h_length);
|
||||
|
||||
if (connect(sockfd, (struct sockaddr *)&sa, sizeof sa) < 0) {
|
||||
saved_errno = errno;
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
continue;
|
||||
|
@ -443,7 +449,7 @@ static int git_tcp_connect_sock(char *host)
|
|||
}
|
||||
|
||||
if (sockfd < 0)
|
||||
die("unable to connect a socket (%s)", strerror(errno));
|
||||
die("unable to connect a socket (%s)", strerror(saved_errno));
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
|
|
@ -264,9 +264,19 @@ when you have upgraded your tools and habits to use refs/remotes/$GIT_SVN
|
|||
}
|
||||
|
||||
sub init {
|
||||
$SVN_URL = shift or die "SVN repository location required " .
|
||||
my $url = shift or die "SVN repository location required " .
|
||||
"as a command-line argument\n";
|
||||
$SVN_URL =~ s!/+$!!; # strip trailing slash
|
||||
$url =~ s!/+$!!; # strip trailing slash
|
||||
|
||||
if (my $repo_path = shift) {
|
||||
unless (-d $repo_path) {
|
||||
mkpath([$repo_path]);
|
||||
}
|
||||
$GIT_DIR = $ENV{GIT_DIR} = $repo_path . "/.git";
|
||||
init_vars();
|
||||
}
|
||||
|
||||
$SVN_URL = $url;
|
||||
unless (-d $GIT_DIR) {
|
||||
my @init_db = ('git-init-db');
|
||||
push @init_db, "--template=$_template" if defined $_template;
|
||||
|
|
|
@ -60,12 +60,13 @@ static int objwarning(struct object *obj, const char *err, ...)
|
|||
|
||||
static void check_connectivity(void)
|
||||
{
|
||||
int i;
|
||||
int i, max;
|
||||
|
||||
/* Look up all the requirements, warn about missing objects.. */
|
||||
for (i = 0; i < obj_allocs; i++) {
|
||||
max = get_max_object_index();
|
||||
for (i = 0; i < max; i++) {
|
||||
const struct object_refs *refs;
|
||||
struct object *obj = objs[i];
|
||||
struct object *obj = get_indexed_object(i);
|
||||
|
||||
if (!obj)
|
||||
continue;
|
||||
|
|
|
@ -29,7 +29,7 @@ THIS_INDEX="$GIT_DIR/index"
|
|||
NEXT_INDEX="$GIT_DIR/next-index$$"
|
||||
rm -f "$NEXT_INDEX"
|
||||
save_index () {
|
||||
cp "$THIS_INDEX" "$NEXT_INDEX"
|
||||
cp -p "$THIS_INDEX" "$NEXT_INDEX"
|
||||
}
|
||||
|
||||
report () {
|
||||
|
|
|
@ -534,7 +534,7 @@ sub commit {
|
|||
my($author_name,$author_email,$dest);
|
||||
my(@old,@new,@parents);
|
||||
|
||||
if (not defined $author) {
|
||||
if (not defined $author or $author eq "") {
|
||||
$author_name = $author_email = "unknown";
|
||||
} elsif (defined $users_file) {
|
||||
die "User $author is not listed in $users_file\n"
|
||||
|
|
13
name-rev.c
13
name-rev.c
|
@ -234,12 +234,15 @@ int main(int argc, char **argv)
|
|||
fwrite(p_start, p - p_start, 1, stdout);
|
||||
}
|
||||
} else if (all) {
|
||||
int i;
|
||||
int i, max;
|
||||
|
||||
for (i = 0; i < obj_allocs; i++)
|
||||
if (objs[i])
|
||||
printf("%s %s\n", sha1_to_hex(objs[i]->sha1),
|
||||
get_rev_name(objs[i]));
|
||||
max = get_max_object_index();
|
||||
for (i = 0; i < max; i++) {
|
||||
struct object * obj = get_indexed_object(i);
|
||||
if (!obj)
|
||||
continue;
|
||||
printf("%s %s\n", sha1_to_hex(obj->sha1), get_rev_name(obj));
|
||||
}
|
||||
} else {
|
||||
int i;
|
||||
for (i = 0; i < revs.nr; i++)
|
||||
|
|
128
object.c
128
object.c
|
@ -5,79 +5,97 @@
|
|||
#include "commit.h"
|
||||
#include "tag.h"
|
||||
|
||||
struct object **objs;
|
||||
static int nr_objs;
|
||||
int obj_allocs;
|
||||
static struct object **obj_hash;
|
||||
static int nr_objs, obj_hash_size;
|
||||
|
||||
unsigned int get_max_object_index(void)
|
||||
{
|
||||
return obj_hash_size;
|
||||
}
|
||||
|
||||
struct object *get_indexed_object(unsigned int idx)
|
||||
{
|
||||
return obj_hash[idx];
|
||||
}
|
||||
|
||||
const char *type_names[] = {
|
||||
"none", "blob", "tree", "commit", "bad"
|
||||
};
|
||||
|
||||
static unsigned int hash_obj(struct object *obj, unsigned int n)
|
||||
{
|
||||
unsigned int hash = *(unsigned int *)obj->sha1;
|
||||
return hash % n;
|
||||
}
|
||||
|
||||
static void insert_obj_hash(struct object *obj, struct object **hash, unsigned int size)
|
||||
{
|
||||
int j = hash_obj(obj, size);
|
||||
|
||||
while (hash[j]) {
|
||||
j++;
|
||||
if (j >= size)
|
||||
j = 0;
|
||||
}
|
||||
hash[j] = obj;
|
||||
}
|
||||
|
||||
static int hashtable_index(const unsigned char *sha1)
|
||||
{
|
||||
unsigned int i;
|
||||
memcpy(&i, sha1, sizeof(unsigned int));
|
||||
return (int)(i % obj_allocs);
|
||||
}
|
||||
|
||||
static int find_object(const unsigned char *sha1)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!objs)
|
||||
return -1;
|
||||
|
||||
i = hashtable_index(sha1);
|
||||
while (objs[i]) {
|
||||
if (memcmp(sha1, objs[i]->sha1, 20) == 0)
|
||||
return i;
|
||||
i++;
|
||||
if (i == obj_allocs)
|
||||
i = 0;
|
||||
}
|
||||
return -1 - i;
|
||||
return (int)(i % obj_hash_size);
|
||||
}
|
||||
|
||||
struct object *lookup_object(const unsigned char *sha1)
|
||||
{
|
||||
int pos = find_object(sha1);
|
||||
if (pos >= 0)
|
||||
return objs[pos];
|
||||
return NULL;
|
||||
int i;
|
||||
struct object *obj;
|
||||
|
||||
if (!obj_hash)
|
||||
return NULL;
|
||||
|
||||
i = hashtable_index(sha1);
|
||||
while ((obj = obj_hash[i]) != NULL) {
|
||||
if (!memcmp(sha1, obj->sha1, 20))
|
||||
break;
|
||||
i++;
|
||||
if (i == obj_hash_size)
|
||||
i = 0;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
static void grow_object_hash(void)
|
||||
{
|
||||
int i;
|
||||
int new_hash_size = obj_hash_size < 32 ? 32 : 2 * obj_hash_size;
|
||||
struct object **new_hash;
|
||||
|
||||
new_hash = calloc(new_hash_size, sizeof(struct object *));
|
||||
for (i = 0; i < obj_hash_size; i++) {
|
||||
struct object *obj = obj_hash[i];
|
||||
if (!obj)
|
||||
continue;
|
||||
insert_obj_hash(obj, new_hash, new_hash_size);
|
||||
}
|
||||
free(obj_hash);
|
||||
obj_hash = new_hash;
|
||||
obj_hash_size = new_hash_size;
|
||||
}
|
||||
|
||||
void created_object(const unsigned char *sha1, struct object *obj)
|
||||
{
|
||||
int pos;
|
||||
|
||||
obj->parsed = 0;
|
||||
memcpy(obj->sha1, sha1, 20);
|
||||
obj->type = TYPE_NONE;
|
||||
obj->used = 0;
|
||||
obj->type = TYPE_NONE;
|
||||
obj->flags = 0;
|
||||
memcpy(obj->sha1, sha1, 20);
|
||||
|
||||
if (obj_allocs - 1 <= nr_objs * 2) {
|
||||
int i, count = obj_allocs;
|
||||
obj_allocs = (obj_allocs < 32 ? 32 : 2 * obj_allocs);
|
||||
objs = xrealloc(objs, obj_allocs * sizeof(struct object *));
|
||||
memset(objs + count, 0, (obj_allocs - count)
|
||||
* sizeof(struct object *));
|
||||
for (i = 0; i < obj_allocs; i++)
|
||||
if (objs[i]) {
|
||||
int j = find_object(objs[i]->sha1);
|
||||
if (j != i) {
|
||||
j = -1 - j;
|
||||
objs[j] = objs[i];
|
||||
objs[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (obj_hash_size - 1 <= nr_objs * 2)
|
||||
grow_object_hash();
|
||||
|
||||
pos = find_object(sha1);
|
||||
if (pos >= 0)
|
||||
die("Inserting %s twice\n", sha1_to_hex(sha1));
|
||||
pos = -pos-1;
|
||||
|
||||
objs[pos] = obj;
|
||||
insert_obj_hash(obj, obj_hash, obj_hash_size);
|
||||
nr_objs++;
|
||||
}
|
||||
|
||||
|
@ -222,7 +240,7 @@ void clear_object_marks(unsigned mark)
|
|||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < obj_allocs; i++)
|
||||
if (objs[i])
|
||||
objs[i]->flags &= ~mark;
|
||||
for (i = 0; i < obj_hash_size; i++)
|
||||
if (obj_hash[i])
|
||||
obj_hash[i]->flags &= ~mark;
|
||||
}
|
||||
|
|
5
object.h
5
object.h
|
@ -40,10 +40,11 @@ struct object {
|
|||
};
|
||||
|
||||
extern int track_object_refs;
|
||||
extern int obj_allocs;
|
||||
extern struct object **objs;
|
||||
extern const char *type_names[];
|
||||
|
||||
extern unsigned int get_max_object_index(void);
|
||||
extern struct object *get_indexed_object(unsigned int);
|
||||
|
||||
static inline const char *typename(unsigned int type)
|
||||
{
|
||||
return type_names[type > TYPE_TAG ? TYPE_BAD : type];
|
||||
|
|
|
@ -970,11 +970,12 @@ struct unpacked {
|
|||
* one.
|
||||
*/
|
||||
static int try_delta(struct unpacked *trg, struct unpacked *src,
|
||||
struct delta_index *src_index, unsigned max_depth)
|
||||
unsigned max_depth)
|
||||
{
|
||||
struct object_entry *trg_entry = trg->entry;
|
||||
struct object_entry *src_entry = src->entry;
|
||||
unsigned long size, src_size, delta_size, sizediff, max_size;
|
||||
unsigned long trg_size, src_size, delta_size, sizediff, max_size, sz;
|
||||
char type[10];
|
||||
void *delta_buf;
|
||||
|
||||
/* Don't bother doing diffs between different types */
|
||||
|
@ -987,6 +988,14 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
|
|||
if (trg_entry->preferred_base)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* We do not bother to try a delta that we discarded
|
||||
* on an earlier try, but only when reusing delta data.
|
||||
*/
|
||||
if (!no_reuse_delta && trg_entry->in_pack &&
|
||||
trg_entry->in_pack == src_entry->in_pack)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If the current object is at pack edge, take the depth the
|
||||
* objects that depend on the current object into account --
|
||||
|
@ -1001,19 +1010,38 @@ static int try_delta(struct unpacked *trg, struct unpacked *src,
|
|||
return 0;
|
||||
|
||||
/* Now some size filtering heuristics. */
|
||||
size = trg_entry->size;
|
||||
max_size = size/2 - 20;
|
||||
trg_size = trg_entry->size;
|
||||
max_size = trg_size/2 - 20;
|
||||
max_size = max_size * (max_depth - src_entry->depth) / max_depth;
|
||||
if (max_size == 0)
|
||||
return 0;
|
||||
if (trg_entry->delta && trg_entry->delta_size <= max_size)
|
||||
max_size = trg_entry->delta_size-1;
|
||||
src_size = src_entry->size;
|
||||
sizediff = src_size < size ? size - src_size : 0;
|
||||
sizediff = src_size < trg_size ? trg_size - src_size : 0;
|
||||
if (sizediff >= max_size)
|
||||
return 0;
|
||||
|
||||
delta_buf = create_delta(src_index, trg->data, size, &delta_size, max_size);
|
||||
/* Load data if not already done */
|
||||
if (!trg->data) {
|
||||
trg->data = read_sha1_file(trg_entry->sha1, type, &sz);
|
||||
if (sz != trg_size)
|
||||
die("object %s inconsistent object length (%lu vs %lu)",
|
||||
sha1_to_hex(trg_entry->sha1), sz, trg_size);
|
||||
}
|
||||
if (!src->data) {
|
||||
src->data = read_sha1_file(src_entry->sha1, type, &sz);
|
||||
if (sz != src_size)
|
||||
die("object %s inconsistent object length (%lu vs %lu)",
|
||||
sha1_to_hex(src_entry->sha1), sz, src_size);
|
||||
}
|
||||
if (!src->index) {
|
||||
src->index = create_delta_index(src->data, src_size);
|
||||
if (!src->index)
|
||||
die("out of memory");
|
||||
}
|
||||
|
||||
delta_buf = create_delta(src->index, trg->data, trg_size, &delta_size, max_size);
|
||||
if (!delta_buf)
|
||||
return 0;
|
||||
|
||||
|
@ -1046,8 +1074,6 @@ static void find_deltas(struct object_entry **list, int window, int depth)
|
|||
while (--i >= 0) {
|
||||
struct object_entry *entry = list[i];
|
||||
struct unpacked *n = array + idx;
|
||||
unsigned long size;
|
||||
char type[10];
|
||||
int j;
|
||||
|
||||
if (!entry->preferred_base)
|
||||
|
@ -1074,11 +1100,8 @@ static void find_deltas(struct object_entry **list, int window, int depth)
|
|||
free_delta_index(n->index);
|
||||
n->index = NULL;
|
||||
free(n->data);
|
||||
n->data = NULL;
|
||||
n->entry = entry;
|
||||
n->data = read_sha1_file(entry->sha1, type, &size);
|
||||
if (size != entry->size)
|
||||
die("object %s inconsistent object length (%lu vs %lu)",
|
||||
sha1_to_hex(entry->sha1), size, entry->size);
|
||||
|
||||
j = window;
|
||||
while (--j > 0) {
|
||||
|
@ -1089,7 +1112,7 @@ static void find_deltas(struct object_entry **list, int window, int depth)
|
|||
m = array + other_idx;
|
||||
if (!m->entry)
|
||||
break;
|
||||
if (try_delta(n, m, m->index, depth) < 0)
|
||||
if (try_delta(n, m, depth) < 0)
|
||||
break;
|
||||
}
|
||||
/* if we made n a delta, and if n is already at max
|
||||
|
@ -1099,10 +1122,6 @@ static void find_deltas(struct object_entry **list, int window, int depth)
|
|||
if (entry->delta && depth <= entry->depth)
|
||||
continue;
|
||||
|
||||
n->index = create_delta_index(n->data, size);
|
||||
if (!n->index)
|
||||
die("out of memory");
|
||||
|
||||
idx++;
|
||||
if (idx >= window)
|
||||
idx = 0;
|
||||
|
|
18
revision.c
18
revision.c
|
@ -280,7 +280,7 @@ int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1)
|
|||
static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
|
||||
{
|
||||
struct commit_list **pp, *parent;
|
||||
int tree_changed = 0;
|
||||
int tree_changed = 0, tree_same = 0;
|
||||
|
||||
if (!commit->tree)
|
||||
return;
|
||||
|
@ -298,6 +298,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
|
|||
parse_commit(p);
|
||||
switch (rev_compare_tree(revs, p->tree, commit->tree)) {
|
||||
case REV_TREE_SAME:
|
||||
tree_same = 1;
|
||||
if (!revs->simplify_history || (p->object.flags & UNINTERESTING)) {
|
||||
/* Even if a merge with an uninteresting
|
||||
* side branch brought the entire change
|
||||
|
@ -334,7 +335,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
|
|||
}
|
||||
die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
|
||||
}
|
||||
if (tree_changed)
|
||||
if (tree_changed && !tree_same)
|
||||
commit->object.flags |= TREECHANGE;
|
||||
}
|
||||
|
||||
|
@ -926,6 +927,8 @@ static int rewrite_one(struct rev_info *revs, struct commit **pp)
|
|||
struct commit *p = *pp;
|
||||
if (!revs->limited)
|
||||
add_parents_to_list(revs, p, &revs->commits);
|
||||
if (p->parents && p->parents->next)
|
||||
return 0;
|
||||
if (p->object.flags & (TREECHANGE | UNINTERESTING))
|
||||
return 0;
|
||||
if (!p->parents)
|
||||
|
@ -1018,8 +1021,15 @@ struct commit *get_revision(struct rev_info *revs)
|
|||
commit->parents && commit->parents->next)
|
||||
continue;
|
||||
if (revs->prune_fn && revs->dense) {
|
||||
if (!(commit->object.flags & TREECHANGE))
|
||||
continue;
|
||||
/* Commit without changes? */
|
||||
if (!(commit->object.flags & TREECHANGE)) {
|
||||
/* drop merges unless we want parenthood */
|
||||
if (!revs->parents)
|
||||
continue;
|
||||
/* non-merge - always ignore it */
|
||||
if (!commit->parents || !commit->parents->next)
|
||||
continue;
|
||||
}
|
||||
if (revs->parents)
|
||||
rewrite_parents(revs, commit);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/poll.h>
|
||||
#include "cache.h"
|
||||
#include "refs.h"
|
||||
#include "pkt-line.h"
|
||||
|
@ -5,9 +8,6 @@
|
|||
#include "object.h"
|
||||
#include "commit.h"
|
||||
#include "exec_cmd.h"
|
||||
#include <signal.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
static const char upload_pack_usage[] = "git-upload-pack [--strict] [--timeout=nn] <dir>";
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче