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

This commit is contained in:
Johannes Sixt
2008-06-19 08:21:32 +02:00
13 changed files with 173 additions and 119 deletions

View File

@@ -18,6 +18,8 @@ Updates since v1.5.5
* "git init" now autodetects the case sensitivity of the filesystem and
sets core.ignorecase accordingly.
* cpio is no longer used; neither "curl" binary (libcurl is still used).
(documentation)
* Many freestanding documentation pages have been converted and made
@@ -110,9 +112,4 @@ Fixes since v1.5.5
All of the fixes in v1.5.5 maintenance series are included in
this release, unless otherwise noted.
--
exec >/var/tmp/1
O=v1.5.6-rc3
echo O=`git describe refs/heads/master`
git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint
And there are too numerous small fixes to otherwise note here ;-)

View File

@@ -43,6 +43,11 @@ unreleased) version of git, that is available from 'master'
branch of the `git.git` repository.
Documentation for older releases are available here:
* link:v1.5.6/git.html[documentation for release 1.5.6]
* release notes for
link:RelNotes-1.5.6.txt[1.5.6],
* link:v1.5.5/git.html[documentation for release 1.5.5]
* release notes for

View File

@@ -1,9 +1,126 @@
path-list API
=============
Talk about <path-list.h>, things like
The path_list API offers a data structure and functions to handle sorted
and unsorted string lists.
* it is not just paths but strings in general;
* the calling sequence.
The name is a bit misleading, a path_list may store not only paths but
strings in general.
(Dscho)
The caller:
. Allocates and clears a `struct path_list` variable.
. Initializes the members. You might want to set the flag `strdup_paths`
if the strings should be strdup()ed. For example, this is necessary
when you add something like git_path("..."), since that function returns
a static buffer that will change with the next call to git_path().
+
If you need something advanced, you can manually malloc() the `items`
member (you need this if you add things later) and you should set the
`nr` and `alloc` members in that case, too.
. Adds new items to the list, using `path_list_append` or `path_list_insert`.
. Can check if a string is in the list using `path_list_has_path` or
`unsorted_path_list_has_path` and get it from the list using
`path_list_lookup` for sorted lists.
. Can sort an unsorted list using `sort_path_list`.
. Finally it should free the list using `path_list_clear`.
Example:
----
struct path_list list;
int i;
memset(&list, 0, sizeof(struct path_list));
path_list_append("foo", &list);
path_list_append("bar", &list);
for (i = 0; i < list.nr; i++)
printf("%s\n", list.items[i].path)
----
NOTE: It is more efficient to build an unsorted list and sort it
afterwards, instead of building a sorted list (`O(n log n)` instead of
`O(n^2)`).
+
However, if you use the list to check if a certain string was added
already, you should not do that (using unsorted_path_list_has_path()),
because the complexity would be quadratic again (but with a worse factor).
Functions
---------
* General ones (works with sorted and unsorted lists as well)
`print_path_list`::
Dump a path_list to stdout, useful mainly for debugging purposes. It
can take an optional header argument and it writes out the
string-pointer pairs of the path_list, each one in its own line.
`path_list_clear`::
Free a path_list. The `path` pointer of the items will be freed in case
the `strdup_paths` member of the path_list is set. The second parameter
controls if the `util` pointer of the items should be freed or not.
* Functions for sorted lists only
`path_list_has_path`::
Determine if the path_list has a given string or not.
`path_list_insert`::
Insert a new element to the path_list. The returned pointer can be handy
if you want to write something to the `util` pointer of the
path_list_item containing the just added string.
+
Since this function uses xrealloc() (which die()s if it fails) if the
list needs to grow, it is safe not to check the pointer. I.e. you may
write `path_list_insert(...)->util = ...;`.
`path_list_lookup`::
Look up a given string in the path_list, returning the containing
path_list_item. If the string is not found, NULL is returned.
* Functions for unsorted lists only
`path_list_append`::
Append a new string to the end of the path_list.
`sort_path_list`::
Make an unsorted list sorted.
`unsorted_path_list_has_path`::
It's like `path_list_has_path()` but for unsorted lists.
+
This function needs to look through all items, as opposed to its
counterpart for sorted lists, which performs a binary search.
Data structures
---------------
* `struct path_list_item`
Represents an item of the list. The `path` member is a pointer to the
string, and you may use the `util` member for any purpose, if you want.
* `struct path_list`
Represents the list itself.
. The array of items are available via the `items` member.
. The `nr` member contains the number of items stored in the list.
. The `alloc` member is used to avoid reallocating at every insertion.
You should not tamper with it.
. Setting the `strdup_paths` member to 1 will strdup() the strings
before adding them, see above.

View File

@@ -63,7 +63,7 @@ command to run in a sub-process.
The caller:
1. allocates and clears (memset(&chld, '0', sizeof(chld));) a
1. allocates and clears (memset(&chld, 0, sizeof(chld));) a
struct child_process variable;
2. initializes the members;
3. calls start_command();
@@ -136,7 +136,7 @@ to produce output that the caller reads.
The caller:
1. allocates and clears (memset(&asy, '0', sizeof(asy));) a
1. allocates and clears (memset(&asy, 0, sizeof(asy));) a
struct async variable;
2. initializes .proc and .data;
3. calls start_async();

View File

@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
DEF_VER=v1.5.5.GIT
DEF_VER=v1.5.6.GIT
LF='
'

View File

@@ -43,7 +43,7 @@ static void read_rr(struct path_list *rr)
; /* do nothing */
if (i == sizeof(buf))
die("filename too long");
path_list_insert(buf, rr)->util = xstrdup(name);
path_list_insert(buf, rr)->util = name;
}
fclose(in);
}

View File

@@ -694,8 +694,6 @@ extern struct ref **get_remote_heads(int in, struct ref **list, int nr_match, ch
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,
const char *idx_path);
extern void prepare_packed_git(void);
extern void reprepare_packed_git(void);

6
date.c
View File

@@ -682,10 +682,8 @@ static void date_am(struct tm *tm, int *num)
static void date_never(struct tm *tm, int *num)
{
tm->tm_mon = tm->tm_wday = tm->tm_yday
= tm->tm_hour = tm->tm_min = tm->tm_sec = 0;
tm->tm_year = 70;
tm->tm_mday = 1;
time_t n = 0;
localtime_r(&n, tm);
}
static const struct special {

View File

@@ -421,7 +421,7 @@ do
else
action=yes
fi
FIRSTLINE=$(head -1 "$dotest/final-commit")
FIRSTLINE=$(sed 1q "$dotest/final-commit")
if test $action = skip
then

View File

@@ -1500,9 +1500,13 @@ sub git_cmd {
return $GIT, '--git-dir='.$git_dir;
}
# returns path to the core git executable and the --git-dir parameter as string
sub git_cmd_str {
return join(' ', git_cmd());
# quote the given arguments for passing them to the shell
# quote_command("command", "arg 1", "arg with ' and ! characters")
# => "'command' 'arg 1' 'arg with '\'' and '\!' characters'"
# Try to avoid using this function wherever possible.
sub quote_command {
return join(' ',
map( { my $a = $_; $a =~ s/(['!])/'\\$1'/g; "'$a'" } @_ ));
}
# get HEAD ref of given project as hash
@@ -2158,49 +2162,6 @@ sub parse_commits {
return wantarray ? @cos : \@cos;
}
# parse ref from ref_file, given by ref_id, with given type
sub parse_ref {
my $ref_file = shift;
my $ref_id = shift;
my $type = shift || git_get_type($ref_id);
my %ref_item;
$ref_item{'type'} = $type;
$ref_item{'id'} = $ref_id;
$ref_item{'epoch'} = 0;
$ref_item{'age'} = "unknown";
if ($type eq "tag") {
my %tag = parse_tag($ref_id);
$ref_item{'comment'} = $tag{'comment'};
if ($tag{'type'} eq "commit") {
my %co = parse_commit($tag{'object'});
$ref_item{'epoch'} = $co{'committer_epoch'};
$ref_item{'age'} = $co{'age_string'};
} elsif (defined($tag{'epoch'})) {
my $age = time - $tag{'epoch'};
$ref_item{'epoch'} = $tag{'epoch'};
$ref_item{'age'} = age_string($age);
}
$ref_item{'reftype'} = $tag{'type'};
$ref_item{'name'} = $tag{'name'};
$ref_item{'refid'} = $tag{'object'};
} elsif ($type eq "commit"){
my %co = parse_commit($ref_id);
$ref_item{'reftype'} = "commit";
$ref_item{'name'} = $ref_file;
$ref_item{'title'} = $co{'title'};
$ref_item{'refid'} = $ref_id;
$ref_item{'epoch'} = $co{'committer_epoch'};
$ref_item{'age'} = $co{'age_string'};
} else {
$ref_item{'reftype'} = $type;
$ref_item{'name'} = $ref_file;
$ref_item{'refid'} = $ref_id;
}
return %ref_item;
}
# parse line of git-diff-tree "raw" output
sub parse_difftree_raw_line {
my $line = shift;
@@ -4633,7 +4594,6 @@ sub git_snapshot {
$hash = git_get_head_hash($project);
}
my $git_command = git_cmd_str();
my $name = $project;
$name =~ s,([^/])/*\.git$,$1,;
$name = basename($name);
@@ -4641,11 +4601,12 @@ sub git_snapshot {
$name =~ s/\047/\047\\\047\047/g;
my $cmd;
$filename .= "-$hash$known_snapshot_formats{$format}{'suffix'}";
$cmd = "$git_command archive " .
"--format=$known_snapshot_formats{$format}{'format'} " .
"--prefix=\'$name\'/ $hash";
$cmd = quote_command(
git_cmd(), 'archive',
"--format=$known_snapshot_formats{$format}{'format'}",
"--prefix=$name/", $hash);
if (exists $known_snapshot_formats{$format}{'compressor'}) {
$cmd .= ' | ' . join ' ', @{$known_snapshot_formats{$format}{'compressor'}};
$cmd .= ' | ' . quote_command(@{$known_snapshot_formats{$format}{'compressor'}});
}
print $cgi->header(
@@ -4858,8 +4819,8 @@ sub git_object {
if ($hash || ($hash_base && !defined $file_name)) {
my $object_id = $hash || $hash_base;
my $git_command = git_cmd_str();
open my $fd, "-|", "$git_command cat-file -t $object_id 2>/dev/null"
open my $fd, "-|", quote_command(
git_cmd(), 'cat-file', '-t', $object_id) . ' 2> /dev/null'
or die_error('404 Not Found', "Object does not exist");
$type = <$fd>;
chomp $type;

View File

@@ -867,8 +867,7 @@ static char *guess_ref(const char *name, struct ref *peer)
static int match_explicit(struct ref *src, struct ref *dst,
struct ref ***dst_tail,
struct refspec *rs,
int errs)
struct refspec *rs)
{
struct ref *matched_src, *matched_dst;
@@ -876,7 +875,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
char *dst_guess;
if (rs->pattern || rs->matching)
return errs;
return 0;
matched_src = matched_dst = NULL;
switch (count_refspec_match(rs->src, src, &matched_src)) {
@@ -889,23 +888,16 @@ static int match_explicit(struct ref *src, struct ref *dst,
*/
matched_src = try_explicit_object_name(rs->src);
if (!matched_src)
error("src refspec %s does not match any.", rs->src);
return error("src refspec %s does not match any.", rs->src);
break;
default:
matched_src = NULL;
error("src refspec %s matches more than one.", rs->src);
break;
return error("src refspec %s matches more than one.", rs->src);
}
if (!matched_src)
errs = 1;
if (!dst_value) {
unsigned char sha1[20];
int flag;
if (!matched_src)
return errs;
dst_value = resolve_ref(matched_src->name, sha1, 1, &flag);
if (!dst_value ||
((flag & REF_ISSYMREF) &&
@@ -936,18 +928,16 @@ static int match_explicit(struct ref *src, struct ref *dst,
dst_value);
break;
}
if (errs || !matched_dst)
return 1;
if (matched_dst->peer_ref) {
errs = 1;
error("dst ref %s receives from more than one src.",
if (!matched_dst)
return -1;
if (matched_dst->peer_ref)
return error("dst ref %s receives from more than one src.",
matched_dst->name);
}
else {
matched_dst->peer_ref = matched_src;
matched_dst->force = rs->force;
}
return errs;
return 0;
}
static int match_explicit_refs(struct ref *src, struct ref *dst,
@@ -956,8 +946,8 @@ static int match_explicit_refs(struct ref *src, struct ref *dst,
{
int i, errs;
for (i = errs = 0; i < rs_nr; i++)
errs |= match_explicit(src, dst, dst_tail, &rs[i], errs);
return -errs;
errs += match_explicit(src, dst, dst_tail, &rs[i]);
return errs;
}
static const struct refspec *check_pattern_match(const struct refspec *rs,

View File

@@ -120,7 +120,7 @@ int safe_create_leading_directories(char *path)
return 0;
}
char * sha1_to_hex(const unsigned char *sha1)
char *sha1_to_hex(const unsigned char *sha1)
{
static int bufno;
static char hexbuffer[4][50];
@@ -835,13 +835,7 @@ struct packed_git *add_packed_git(const char *path, int path_len, int local)
struct packed_git *parse_pack_index(unsigned char *sha1)
{
char *path = sha1_pack_index_name(sha1);
return parse_pack_index_file(sha1, path);
}
struct packed_git *parse_pack_index_file(const unsigned char *sha1,
const char *idx_path)
{
const char *idx_path = sha1_pack_index_name(sha1);
const char *path = sha1_pack_name(sha1);
struct packed_git *p = xmalloc(sizeof(*p) + strlen(path) + 2);
@@ -2129,7 +2123,7 @@ static int create_tmpfile(char *buffer, size_t bufsiz, const char *filename)
if (fd < 0 && dirlen) {
/* Make sure the directory exists */
buffer[dirlen-1] = 0;
if (mkdir(buffer, 0777) && adjust_shared_perm(buffer))
if (mkdir(buffer, 0777) || adjust_shared_perm(buffer))
return -1;
/* Try again */
@@ -2149,20 +2143,6 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
static char tmpfile[PATH_MAX];
filename = sha1_file_name(sha1);
fd = open(filename, O_RDONLY);
if (fd >= 0) {
/*
* FIXME!!! We might do collision checking here, but we'd
* need to uncompress the old file and check it. Later.
*/
close(fd);
return 0;
}
if (errno != ENOENT) {
return error("sha1 file %s: %s\n", filename, strerror(errno));
}
fd = create_tmpfile(tmpfile, sizeof(tmpfile), filename);
if (fd < 0) {
if (errno == EPERM)

View File

@@ -37,7 +37,8 @@ test_expect_success "clone and setup child repos" '
echo "Pull: refs/heads/one:refs/heads/one"
} >.git/remotes/two &&
cd .. &&
git clone . bundle
git clone . bundle &&
git clone . seven
'
test_expect_success "fetch test" '
@@ -295,4 +296,11 @@ test_expect_success 'configured fetch updates tracking' '
)
'
test_expect_success 'pushing nonexistent branch by mistake should not segv' '
cd "$D" &&
test_must_fail git push seven no:no
'
test_done