mirror of
https://github.com/git/git.git
synced 2026-03-14 10:53:25 +01:00
Merge branch 'np/index-pack' into next
* np/index-pack: enable index-pack streaming capability Documentation/SubmittingPatches: 3+1 != 6 xdiff: Match GNU diff behaviour when deciding hunk comment worthiness of lines Update cherry documentation. Refer to git-rev-parse:Specifying Revisions from git.txt git-fetch.sh printed protocol fix RPM package re-classification. Documentation: note about contrib/. git-svn: fix symlink-to-file changes when using command-line svn 1.4.0 Set $HOME for selftests
This commit is contained in:
@@ -101,8 +101,13 @@ send it "To:" the mailing list, and optionally "cc:" him. If it
|
||||
is trivially correct or after the list reached a consensus, send
|
||||
it "To:" the maintainer and optionally "cc:" the list.
|
||||
|
||||
Also note that your maintainer does not actively involve himself in
|
||||
maintaining what are in contrib/ hierarchy. When you send fixes and
|
||||
enhancements to them, do not forget to "cc: " the person who primarily
|
||||
worked on that hierarchy in contrib/.
|
||||
|
||||
(6) Sign your work
|
||||
|
||||
(4) Sign your work
|
||||
|
||||
To improve tracking of who did what, we've borrowed the
|
||||
"sign-off" procedure from the Linux kernel project on patches
|
||||
|
||||
@@ -14,8 +14,9 @@ DESCRIPTION
|
||||
The changeset (or "diff") of each commit between the fork-point and <head>
|
||||
is compared against each commit between the fork-point and <upstream>.
|
||||
|
||||
Every commit with a changeset that doesn't exist in the other branch
|
||||
has its id (sha1) reported, prefixed by a symbol. Those existing only
|
||||
Every commit that doesn't exist in the <upstream> branch
|
||||
has its id (sha1) reported, prefixed by a symbol. The ones that have
|
||||
equivalent change already
|
||||
in the <upstream> branch are prefixed with a minus (-) sign, and those
|
||||
that only exist in the <head> branch are prefixed with a plus (+) symbol.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ git-index-pack - Build pack index file for an existing packed archive
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
'git-index-pack' [-o <index-file>] <pack-file>
|
||||
'git-index-pack' [-o <index-file>] { <pack-file> | --stdin [<pack-file>] }
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
@@ -29,6 +29,12 @@ OPTIONS
|
||||
fails if the name of packed archive does not end
|
||||
with .pack).
|
||||
|
||||
--stdin::
|
||||
When this flag is provided, the pack is read from stdin
|
||||
instead and a copy is then written to <pack-file>. If
|
||||
<pack-file> is not specified, the pack is written to
|
||||
objects/pack/ directory of the current git repository with
|
||||
a default name determined from the pack content.
|
||||
|
||||
Author
|
||||
------
|
||||
|
||||
@@ -565,6 +565,9 @@ HEAD::
|
||||
a valid head 'name'
|
||||
(i.e. the contents of `$GIT_DIR/refs/heads/<head>`).
|
||||
|
||||
For a more complete list of ways to spell object names, see
|
||||
"SPECIFYING REVISIONS" section in gitlink:git-rev-parse[1].
|
||||
|
||||
|
||||
File/Directory Structure
|
||||
------------------------
|
||||
|
||||
@@ -296,6 +296,7 @@ fetch_main () {
|
||||
# There are transports that can fetch only one head at a time...
|
||||
case "$remote" in
|
||||
http://* | https://* | ftp://*)
|
||||
proto=`expr "$remote" : '\([^:]*\):'`
|
||||
if [ -n "$GIT_SSL_NO_VERIFY" ]; then
|
||||
curl_extra_args="-k"
|
||||
fi
|
||||
@@ -319,7 +320,7 @@ fetch_main () {
|
||||
done
|
||||
expr "z$head" : "z$_x40\$" >/dev/null ||
|
||||
die "Failed to fetch $remote_name from $remote"
|
||||
echo >&2 Fetching "$remote_name from $remote" using http
|
||||
echo >&2 "Fetching $remote_name from $remote using $proto"
|
||||
git-http-fetch -v -a "$head" "$remote/" || exit
|
||||
;;
|
||||
rsync://*)
|
||||
|
||||
@@ -1501,10 +1501,13 @@ sub svn_checkout_tree {
|
||||
apply_mod_line_blob($m);
|
||||
svn_check_prop_executable($m);
|
||||
} elsif ($m->{chg} eq 'T') {
|
||||
sys(qw(svn rm --force),$m->{file_b});
|
||||
apply_mod_line_blob($m);
|
||||
sys(qw(svn add), $m->{file_b});
|
||||
svn_check_prop_executable($m);
|
||||
apply_mod_line_blob($m);
|
||||
if ($m->{mode_a} =~ /^120/ && $m->{mode_b} !~ /^120/) {
|
||||
sys(qw(svn propdel svn:special), $m->{file_b});
|
||||
} else {
|
||||
sys(qw(svn propset svn:special *),$m->{file_b});
|
||||
}
|
||||
} elsif ($m->{chg} eq 'A') {
|
||||
svn_ensure_parent_path( $m->{file_b} );
|
||||
apply_mod_line_blob($m);
|
||||
|
||||
12
git.spec.in
12
git.spec.in
@@ -96,10 +96,10 @@ find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';'
|
||||
find $RPM_BUILD_ROOT -type f -name '*.bs' -empty -exec rm -f {} ';'
|
||||
find $RPM_BUILD_ROOT -type f -name perllocal.pod -exec rm -f {} ';'
|
||||
|
||||
(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "arch|svn|cvs|email|gitk" | sed -e s@^$RPM_BUILD_ROOT@@) > bin-man-doc-files
|
||||
(find $RPM_BUILD_ROOT%{_bindir} -type f | grep -vE "archimport|svn|cvs|email|gitk" | sed -e s@^$RPM_BUILD_ROOT@@) > bin-man-doc-files
|
||||
(find $RPM_BUILD_ROOT%{perl_vendorlib} -type f | sed -e s@^$RPM_BUILD_ROOT@@) >> perl-files
|
||||
%if %{!?_without_docs:1}0
|
||||
(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "arch|svn|git-cvs|email|gitk" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
|
||||
(find $RPM_BUILD_ROOT%{_mandir} $RPM_BUILD_ROOT/Documentation -type f | grep -vE "archimport|svn|git-cvs|email|gitk" | sed -e s@^$RPM_BUILD_ROOT@@ -e 's/$/*/' ) >> bin-man-doc-files
|
||||
%else
|
||||
rm -rf $RPM_BUILD_ROOT%{_mandir}
|
||||
%endif
|
||||
@@ -126,10 +126,10 @@ rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files arch
|
||||
%defattr(-,root,root)
|
||||
%doc Documentation/*arch*.txt
|
||||
%{_bindir}/*arch*
|
||||
%{!?_without_docs: %{_mandir}/man1/*arch*.1*}
|
||||
%{!?_without_docs: %doc Documentation/*arch*.html }
|
||||
%doc Documentation/git-archimport.txt
|
||||
%{_bindir}/git-archimport
|
||||
%{!?_without_docs: %{_mandir}/man1/git-archimport.1*}
|
||||
%{!?_without_docs: %doc Documentation/git-archimport.html }
|
||||
|
||||
%files email
|
||||
%defattr(-,root,root)
|
||||
|
||||
133
index-pack.c
133
index-pack.c
@@ -8,7 +8,7 @@
|
||||
#include "tree.h"
|
||||
|
||||
static const char index_pack_usage[] =
|
||||
"git-index-pack [-o index-file] pack-file";
|
||||
"git-index-pack [-o <index-file>] { <pack-file> | --stdin [<pack-file>] }";
|
||||
|
||||
struct object_entry
|
||||
{
|
||||
@@ -37,17 +37,18 @@ struct delta_entry
|
||||
union delta_base base;
|
||||
};
|
||||
|
||||
static const char *pack_name;
|
||||
static struct object_entry *objects;
|
||||
static struct delta_entry *deltas;
|
||||
static int nr_objects;
|
||||
static int nr_deltas;
|
||||
|
||||
static int from_stdin;
|
||||
|
||||
/* We always read in 4kB chunks. */
|
||||
static unsigned char input_buffer[4096];
|
||||
static unsigned long input_offset, input_len, consumed_bytes;
|
||||
static SHA_CTX input_ctx;
|
||||
static int input_fd;
|
||||
static int input_fd, output_fd, mmap_fd;
|
||||
|
||||
/*
|
||||
* Make sure at least "min" bytes are available in the buffer, and
|
||||
@@ -60,6 +61,8 @@ static void * fill(int min)
|
||||
if (min > sizeof(input_buffer))
|
||||
die("cannot fill %d bytes", min);
|
||||
if (input_offset) {
|
||||
if (output_fd >= 0)
|
||||
write_or_die(output_fd, input_buffer, input_offset);
|
||||
SHA1_Update(&input_ctx, input_buffer, input_offset);
|
||||
memcpy(input_buffer, input_buffer + input_offset, input_len);
|
||||
input_offset = 0;
|
||||
@@ -86,13 +89,31 @@ static void use(int bytes)
|
||||
consumed_bytes += bytes;
|
||||
}
|
||||
|
||||
static void open_pack_file(void)
|
||||
static const char * open_pack_file(const char *pack_name)
|
||||
{
|
||||
input_fd = open(pack_name, O_RDONLY);
|
||||
if (input_fd < 0)
|
||||
die("cannot open packfile '%s': %s", pack_name,
|
||||
strerror(errno));
|
||||
if (from_stdin) {
|
||||
input_fd = 0;
|
||||
if (!pack_name) {
|
||||
static char tmpfile[PATH_MAX];
|
||||
snprintf(tmpfile, sizeof(tmpfile),
|
||||
"%s/pack_XXXXXX", get_object_directory());
|
||||
output_fd = mkstemp(tmpfile);
|
||||
pack_name = xstrdup(tmpfile);
|
||||
} else
|
||||
output_fd = open(pack_name, O_CREAT|O_EXCL|O_RDWR, 0600);
|
||||
if (output_fd < 0)
|
||||
die("unable to create %s: %s\n", pack_name, strerror(errno));
|
||||
mmap_fd = output_fd;
|
||||
} else {
|
||||
input_fd = open(pack_name, O_RDONLY);
|
||||
if (input_fd < 0)
|
||||
die("cannot open packfile '%s': %s",
|
||||
pack_name, strerror(errno));
|
||||
output_fd = -1;
|
||||
mmap_fd = input_fd;
|
||||
}
|
||||
SHA1_Init(&input_ctx);
|
||||
return pack_name;
|
||||
}
|
||||
|
||||
static void parse_pack_header(void)
|
||||
@@ -101,10 +122,9 @@ static void parse_pack_header(void)
|
||||
|
||||
/* Header consistency check */
|
||||
if (hdr->hdr_signature != htonl(PACK_SIGNATURE))
|
||||
die("packfile '%s' signature mismatch", pack_name);
|
||||
die("pack signature mismatch");
|
||||
if (!pack_version_ok(hdr->hdr_version))
|
||||
die("packfile '%s' version %d unsupported",
|
||||
pack_name, ntohl(hdr->hdr_version));
|
||||
die("pack version %d unsupported", ntohl(hdr->hdr_version));
|
||||
|
||||
nr_objects = ntohl(hdr->hdr_entries);
|
||||
use(sizeof(struct pack_header));
|
||||
@@ -122,8 +142,7 @@ static void bad_object(unsigned long offset, const char *format, ...)
|
||||
va_start(params, format);
|
||||
vsnprintf(buf, sizeof(buf), format, params);
|
||||
va_end(params);
|
||||
die("packfile '%s': bad object at offset %lu: %s",
|
||||
pack_name, offset, buf);
|
||||
die("pack has bad object at offset %lu: %s", offset, buf);
|
||||
}
|
||||
|
||||
static void *unpack_entry_data(unsigned long offset, unsigned long size)
|
||||
@@ -222,9 +241,9 @@ static void * get_data_from_pack(struct object_entry *obj)
|
||||
int st;
|
||||
|
||||
map = mmap(NULL, len + pg_offset, PROT_READ, MAP_PRIVATE,
|
||||
input_fd, from - pg_offset);
|
||||
mmap_fd, from - pg_offset);
|
||||
if (map == MAP_FAILED)
|
||||
die("cannot mmap packfile '%s': %s", pack_name, strerror(errno));
|
||||
die("cannot mmap pack file: %s", strerror(errno));
|
||||
data = xmalloc(obj->size);
|
||||
memset(&stream, 0, sizeof(stream));
|
||||
stream.next_out = data;
|
||||
@@ -382,14 +401,16 @@ static void parse_pack_objects(unsigned char *sha1)
|
||||
SHA1_Update(&input_ctx, input_buffer, input_offset);
|
||||
SHA1_Final(sha1, &input_ctx);
|
||||
if (hashcmp(fill(20), sha1))
|
||||
die("packfile '%s' SHA1 mismatch", pack_name);
|
||||
die("pack is corrupted (SHA1 mismatch)");
|
||||
use(20);
|
||||
if (output_fd >= 0)
|
||||
write_or_die(output_fd, input_buffer, input_offset);
|
||||
|
||||
/* If input_fd is a file, we should have reached its end now. */
|
||||
if (fstat(input_fd, &st))
|
||||
die("cannot fstat packfile '%s': %s", pack_name, strerror(errno));
|
||||
die("cannot fstat packfile: %s", strerror(errno));
|
||||
if (S_ISREG(st.st_mode) && st.st_size != consumed_bytes)
|
||||
die("packfile '%s' has junk at the end", pack_name);
|
||||
die("pack has junk at the end");
|
||||
|
||||
/* Sort deltas by base SHA1/offset for fast searching */
|
||||
qsort(deltas, nr_deltas, sizeof(struct delta_entry),
|
||||
@@ -435,7 +456,7 @@ static void parse_pack_objects(unsigned char *sha1)
|
||||
for (i = 0; i < nr_deltas; i++) {
|
||||
if (deltas[i].obj->real_type == OBJ_REF_DELTA ||
|
||||
deltas[i].obj->real_type == OBJ_OFS_DELTA)
|
||||
die("packfile '%s' has unresolved deltas", pack_name);
|
||||
die("pack has unresolved deltas");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -450,12 +471,12 @@ static int sha1_compare(const void *_a, const void *_b)
|
||||
* On entry *sha1 contains the pack content SHA1 hash, on exit it is
|
||||
* the SHA1 hash of sorted object names.
|
||||
*/
|
||||
static void write_index_file(const char *index_name, unsigned char *sha1)
|
||||
static const char * write_index_file(const char *index_name, unsigned char *sha1)
|
||||
{
|
||||
struct sha1file *f;
|
||||
struct object_entry **sorted_by_sha, **list, **last;
|
||||
unsigned int array[256];
|
||||
int i;
|
||||
int i, fd;
|
||||
SHA_CTX ctx;
|
||||
|
||||
if (nr_objects) {
|
||||
@@ -472,8 +493,19 @@ static void write_index_file(const char *index_name, unsigned char *sha1)
|
||||
else
|
||||
sorted_by_sha = list = last = NULL;
|
||||
|
||||
unlink(index_name);
|
||||
f = sha1create("%s", index_name);
|
||||
if (!index_name) {
|
||||
static char tmpfile[PATH_MAX];
|
||||
snprintf(tmpfile, sizeof(tmpfile),
|
||||
"%s/index_XXXXXX", get_object_directory());
|
||||
fd = mkstemp(tmpfile);
|
||||
index_name = xstrdup(tmpfile);
|
||||
} else {
|
||||
unlink(index_name);
|
||||
fd = open(index_name, O_CREAT|O_EXCL|O_WRONLY, 0600);
|
||||
}
|
||||
if (fd < 0)
|
||||
die("unable to create %s: %s", index_name, strerror(errno));
|
||||
f = sha1fd(fd, index_name);
|
||||
|
||||
/*
|
||||
* Write the first-level table (the list is sorted,
|
||||
@@ -513,12 +545,52 @@ static void write_index_file(const char *index_name, unsigned char *sha1)
|
||||
sha1close(f, NULL, 1);
|
||||
free(sorted_by_sha);
|
||||
SHA1_Final(sha1, &ctx);
|
||||
return index_name;
|
||||
}
|
||||
|
||||
static void final(const char *final_pack_name, const char *curr_pack_name,
|
||||
const char *final_index_name, const char *curr_index_name,
|
||||
unsigned char *sha1)
|
||||
{
|
||||
char name[PATH_MAX];
|
||||
int err;
|
||||
|
||||
if (!from_stdin) {
|
||||
close(input_fd);
|
||||
} else {
|
||||
err = close(output_fd);
|
||||
if (err)
|
||||
die("error while closing pack file: %s", strerror(errno));
|
||||
chmod(curr_pack_name, 0444);
|
||||
}
|
||||
|
||||
if (final_pack_name != curr_pack_name) {
|
||||
if (!final_pack_name) {
|
||||
snprintf(name, sizeof(name), "%s/pack/pack-%s.pack",
|
||||
get_object_directory(), sha1_to_hex(sha1));
|
||||
final_pack_name = name;
|
||||
}
|
||||
if (move_temp_to_file(curr_pack_name, final_pack_name))
|
||||
die("cannot store pack file");
|
||||
}
|
||||
|
||||
chmod(curr_index_name, 0444);
|
||||
if (final_index_name != curr_index_name) {
|
||||
if (!final_index_name) {
|
||||
snprintf(name, sizeof(name), "%s/pack/pack-%s.idx",
|
||||
get_object_directory(), sha1_to_hex(sha1));
|
||||
final_index_name = name;
|
||||
}
|
||||
if (move_temp_to_file(curr_index_name, final_index_name))
|
||||
die("cannot store index file");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
char *index_name = NULL;
|
||||
const char *curr_pack, *pack_name = NULL;
|
||||
const char *curr_index, *index_name = NULL;
|
||||
char *index_name_buf = NULL;
|
||||
unsigned char sha1[20];
|
||||
|
||||
@@ -526,7 +598,9 @@ int main(int argc, char **argv)
|
||||
const char *arg = argv[i];
|
||||
|
||||
if (*arg == '-') {
|
||||
if (!strcmp(arg, "-o")) {
|
||||
if (!strcmp(arg, "--stdin")) {
|
||||
from_stdin = 1;
|
||||
} else if (!strcmp(arg, "-o")) {
|
||||
if (index_name || (i+1) >= argc)
|
||||
usage(index_pack_usage);
|
||||
index_name = argv[++i];
|
||||
@@ -540,9 +614,9 @@ int main(int argc, char **argv)
|
||||
pack_name = arg;
|
||||
}
|
||||
|
||||
if (!pack_name)
|
||||
if (!pack_name && !from_stdin)
|
||||
usage(index_pack_usage);
|
||||
if (!index_name) {
|
||||
if (!index_name && pack_name) {
|
||||
int len = strlen(pack_name);
|
||||
if (!has_extension(pack_name, ".pack"))
|
||||
die("packfile name '%s' does not end with '.pack'",
|
||||
@@ -553,13 +627,14 @@ int main(int argc, char **argv)
|
||||
index_name = index_name_buf;
|
||||
}
|
||||
|
||||
open_pack_file();
|
||||
curr_pack = open_pack_file(pack_name);
|
||||
parse_pack_header();
|
||||
objects = xcalloc(nr_objects + 1, sizeof(struct object_entry));
|
||||
deltas = xcalloc(nr_objects, sizeof(struct delta_entry));
|
||||
parse_pack_objects(sha1);
|
||||
free(deltas);
|
||||
write_index_file(index_name, sha1);
|
||||
curr_index = write_index_file(index_name, sha1);
|
||||
final(pack_name, curr_pack, index_name, curr_index, sha1);
|
||||
free(objects);
|
||||
free(index_name_buf);
|
||||
|
||||
|
||||
@@ -207,7 +207,8 @@ test_done () {
|
||||
# t/ subdirectory and are run in trash subdirectory.
|
||||
PATH=$(pwd)/..:$PATH
|
||||
GIT_EXEC_PATH=$(pwd)/..
|
||||
export PATH GIT_EXEC_PATH
|
||||
HOME=$(pwd)/trash
|
||||
export PATH GIT_EXEC_PATH HOME
|
||||
|
||||
# Similarly use ../compat/subprocess.py if our python does not
|
||||
# have subprocess.py on its own.
|
||||
|
||||
@@ -86,8 +86,7 @@ static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) {
|
||||
if (len > 0 &&
|
||||
(isalpha((unsigned char)*rec) || /* identifier? */
|
||||
*rec == '_' || /* also identifier? */
|
||||
*rec == '(' || /* lisp defun? */
|
||||
*rec == '#')) { /* #define? */
|
||||
*rec == '$')) { /* mysterious GNU diff's invention */
|
||||
if (len > sz)
|
||||
len = sz;
|
||||
while (0 < len && isspace((unsigned char)rec[len - 1]))
|
||||
|
||||
Reference in New Issue
Block a user