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:
Junio C Hamano 2006-07-03 03:14:32 -07:00
commit f23c75a8ec
13 changed files with 172 additions and 104 deletions

View File

@ -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].

View File

@ -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)

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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 () {

View File

@ -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"

View File

@ -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
View File

@ -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;
}

View File

@ -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];

View File

@ -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;

View File

@ -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);
}

View File

@ -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>";