Merge branch 'master' into ph/strbuf

* master:
  archive - leakfix for format_subst()
  Make --no-thin the default in git-push to save server resources
  fix doc for --compression argument to pack-objects
  git-tag -s must fail if gpg cannot sign the tag.
  git-svn: understand grafts when doing dcommit
  git-diff: don't squelch the new SHA1 in submodule diffs
  Define NO_MEMMEM on Darwin as it lacks the function
  git-svn: fix "Malformed network data" with svn:// servers
  (cvs|svn)import: Ask git-tag to overwrite old tags.
  git-rebase: fix -C option
  git-rebase: support --whitespace=<option>
  Documentation / grammer nit
  archive: rename attribute specfile to export-subst
  archive: specfile syntax change: "$Format:%PLCHLDR$" instead of just "%PLCHLDR" (take 2)
  add memmem()
  Remove unused function convert_sha1_file()
  archive: specfile support (--pretty=format: in archive files)
  Export format_commit_message()
This commit is contained in:
Junio C Hamano 2007-09-10 11:32:58 -07:00
commit ddb95de33e
25 changed files with 272 additions and 54 deletions

View File

@ -68,7 +68,7 @@ OPTIONS
automatically setup .git/objects/info/alternates to automatically setup .git/objects/info/alternates to
obtain objects from the reference repository. Using obtain objects from the reference repository. Using
an already existing repository as an alternate will an already existing repository as an alternate will
require less objects to be copied from the repository require fewer objects to be copied from the repository
being cloned, reducing network and local storage costs. being cloned, reducing network and local storage costs.
--quiet:: --quiet::

View File

@ -155,12 +155,8 @@ base-name::
generated pack. If not specified, pack compression level is generated pack. If not specified, pack compression level is
determined first by pack.compression, then by core.compression, determined first by pack.compression, then by core.compression,
and defaults to -1, the zlib default, if neither is set. and defaults to -1, the zlib default, if neither is set.
Data copied from loose objects will be recompressed Add \--no-reuse-object if you want to force a uniform compression
if core.legacyheaders was true when they were created or if level on all data no matter the source.
the loose compression level (see core.loosecompression and
core.compression) is now a different value than the pack
compression level. Add --no-reuse-object if you want to force
a uniform compression level on all data no matter the source.
--delta-base-offset:: --delta-base-offset::
A packed archive can express base object of a delta as A packed archive can express base object of a delta as

View File

@ -8,8 +8,9 @@ git-rebase - Forward-port local commits to the updated upstream head
SYNOPSIS SYNOPSIS
-------- --------
[verse] [verse]
'git-rebase' [-i | --interactive] [-v | --verbose] [-m | --merge] [-C<n>] 'git-rebase' [-i | --interactive] [-v | --verbose] [-m | --merge]
[-p | --preserve-merges] [--onto <newbase>] <upstream> [<branch>] [-C<n>] [ --whitespace=<option>] [-p | --preserve-merges]
[--onto <newbase>] <upstream> [<branch>]
'git-rebase' --continue | --skip | --abort 'git-rebase' --continue | --skip | --abort
DESCRIPTION DESCRIPTION
@ -209,6 +210,10 @@ OPTIONS
context exist they all must match. By default no context is context exist they all must match. By default no context is
ever ignored. ever ignored.
--whitespace=<nowarn|warn|error|error-all|strip>::
This flag is passed to the `git-apply` program
(see gitlink:git-apply[1]) that applies the patch.
-i, \--interactive:: -i, \--interactive::
Make a list of the commits which are about to be rebased. Let the Make a list of the commits which are about to be rebased. Let the
user edit that list before rebasing. This mode can also be used to user edit that list before rebasing. This mode can also be used to

View File

@ -421,6 +421,23 @@ frotz unspecified
---------------------------------------------------------------- ----------------------------------------------------------------
Creating an archive
~~~~~~~~~~~~~~~~~~~
`export-subst`
^^^^^^^^^^^^^^
If the attribute `export-subst` is set for a file then git will expand
several placeholders when adding this file to an archive. The
expansion depends on the availability of a commit ID, i.e. if
gitlink:git-archive[1] has been given a tree instead of a commit or a
tag then no replacement will be done. The placeholders are the same
as those for the option `--pretty=format:` of gitlink:git-log[1],
except that they need to be wrapped like this: `$Format:PLACEHOLDERS$`
in the file. E.g. the string `$Format:%H$` will be replaced by the
commit hash.
GIT GIT
--- ---
Part of the gitlink:git[7] suite Part of the gitlink:git[7] suite

View File

@ -28,6 +28,8 @@ all::
# #
# Define NO_STRCASESTR if you don't have strcasestr. # Define NO_STRCASESTR if you don't have strcasestr.
# #
# Define NO_MEMMEM if you don't have memmem.
#
# Define NO_STRLCPY if you don't have strlcpy. # Define NO_STRLCPY if you don't have strlcpy.
# #
# Define NO_STRTOUMAX if you don't have strtoumax in the C library. # Define NO_STRTOUMAX if you don't have strtoumax in the C library.
@ -396,12 +398,14 @@ ifeq ($(uname_S),Darwin)
NEEDS_LIBICONV = YesPlease NEEDS_LIBICONV = YesPlease
OLD_ICONV = UnfortunatelyYes OLD_ICONV = UnfortunatelyYes
NO_STRLCPY = YesPlease NO_STRLCPY = YesPlease
NO_MEMMEM = YesPlease
endif endif
ifeq ($(uname_S),SunOS) ifeq ($(uname_S),SunOS)
NEEDS_SOCKET = YesPlease NEEDS_SOCKET = YesPlease
NEEDS_NSL = YesPlease NEEDS_NSL = YesPlease
SHELL_PATH = /bin/bash SHELL_PATH = /bin/bash
NO_STRCASESTR = YesPlease NO_STRCASESTR = YesPlease
NO_MEMMEM = YesPlease
NO_HSTRERROR = YesPlease NO_HSTRERROR = YesPlease
ifeq ($(uname_R),5.8) ifeq ($(uname_R),5.8)
NEEDS_LIBICONV = YesPlease NEEDS_LIBICONV = YesPlease
@ -424,6 +428,7 @@ ifeq ($(uname_O),Cygwin)
NO_D_TYPE_IN_DIRENT = YesPlease NO_D_TYPE_IN_DIRENT = YesPlease
NO_D_INO_IN_DIRENT = YesPlease NO_D_INO_IN_DIRENT = YesPlease
NO_STRCASESTR = YesPlease NO_STRCASESTR = YesPlease
NO_MEMMEM = YesPlease
NO_SYMLINK_HEAD = YesPlease NO_SYMLINK_HEAD = YesPlease
NEEDS_LIBICONV = YesPlease NEEDS_LIBICONV = YesPlease
NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
@ -442,6 +447,7 @@ ifeq ($(uname_S),FreeBSD)
endif endif
ifeq ($(uname_S),OpenBSD) ifeq ($(uname_S),OpenBSD)
NO_STRCASESTR = YesPlease NO_STRCASESTR = YesPlease
NO_MEMMEM = YesPlease
NEEDS_LIBICONV = YesPlease NEEDS_LIBICONV = YesPlease
BASIC_CFLAGS += -I/usr/local/include BASIC_CFLAGS += -I/usr/local/include
BASIC_LDFLAGS += -L/usr/local/lib BASIC_LDFLAGS += -L/usr/local/lib
@ -456,6 +462,7 @@ ifeq ($(uname_S),NetBSD)
endif endif
ifeq ($(uname_S),AIX) ifeq ($(uname_S),AIX)
NO_STRCASESTR=YesPlease NO_STRCASESTR=YesPlease
NO_MEMMEM = YesPlease
NO_STRLCPY = YesPlease NO_STRLCPY = YesPlease
NEEDS_LIBICONV=YesPlease NEEDS_LIBICONV=YesPlease
endif endif
@ -467,6 +474,7 @@ ifeq ($(uname_S),IRIX64)
NO_IPV6=YesPlease NO_IPV6=YesPlease
NO_SETENV=YesPlease NO_SETENV=YesPlease
NO_STRCASESTR=YesPlease NO_STRCASESTR=YesPlease
NO_MEMMEM = YesPlease
NO_STRLCPY = YesPlease NO_STRLCPY = YesPlease
NO_SOCKADDR_STORAGE=YesPlease NO_SOCKADDR_STORAGE=YesPlease
SHELL_PATH=/usr/gnu/bin/bash SHELL_PATH=/usr/gnu/bin/bash
@ -661,6 +669,10 @@ ifdef NO_HSTRERROR
COMPAT_CFLAGS += -DNO_HSTRERROR COMPAT_CFLAGS += -DNO_HSTRERROR
COMPAT_OBJS += compat/hstrerror.o COMPAT_OBJS += compat/hstrerror.o
endif endif
ifdef NO_MEMMEM
COMPAT_CFLAGS += -DNO_MEMMEM
COMPAT_OBJS += compat/memmem.o
endif
ifeq ($(TCLTK_PATH),) ifeq ($(TCLTK_PATH),)
NO_TCLTK=NoThanks NO_TCLTK=NoThanks

View File

@ -17,6 +17,7 @@ static unsigned long offset;
static time_t archive_time; static time_t archive_time;
static int tar_umask = 002; static int tar_umask = 002;
static int verbose; static int verbose;
static const struct commit *commit;
/* writes out the whole block, but only if it is full */ /* writes out the whole block, but only if it is full */
static void write_if_needed(void) static void write_if_needed(void)
@ -252,7 +253,8 @@ static int write_tar_entry(const unsigned char *sha1,
buffer = NULL; buffer = NULL;
size = 0; size = 0;
} else { } else {
buffer = convert_sha1_file(path.buf, sha1, mode, &type, &size); buffer = sha1_file_to_archive(path.buf, sha1, mode, &type,
&size, commit);
if (!buffer) if (!buffer)
die("cannot read %s", sha1_to_hex(sha1)); die("cannot read %s", sha1_to_hex(sha1));
} }
@ -271,6 +273,7 @@ int write_tar_archive(struct archiver_args *args)
archive_time = args->time; archive_time = args->time;
verbose = args->verbose; verbose = args->verbose;
commit = args->commit;
if (args->commit_sha1) if (args->commit_sha1)
write_global_extended_header(args->commit_sha1); write_global_extended_header(args->commit_sha1);

View File

@ -12,6 +12,7 @@
static int verbose; static int verbose;
static int zip_date; static int zip_date;
static int zip_time; static int zip_time;
static const struct commit *commit;
static unsigned char *zip_dir; static unsigned char *zip_dir;
static unsigned int zip_dir_size; static unsigned int zip_dir_size;
@ -195,7 +196,8 @@ static int write_zip_entry(const unsigned char *sha1,
if (S_ISREG(mode) && zlib_compression_level != 0) if (S_ISREG(mode) && zlib_compression_level != 0)
method = 8; method = 8;
result = 0; result = 0;
buffer = convert_sha1_file(path, sha1, mode, &type, &size); buffer = sha1_file_to_archive(path, sha1, mode, &type, &size,
commit);
if (!buffer) if (!buffer)
die("cannot read %s", sha1_to_hex(sha1)); die("cannot read %s", sha1_to_hex(sha1));
crc = crc32(crc, buffer, size); crc = crc32(crc, buffer, size);
@ -316,6 +318,7 @@ int write_zip_archive(struct archiver_args *args)
zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE); zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
zip_dir_size = ZIP_DIRECTORY_MIN_SIZE; zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
verbose = args->verbose; verbose = args->verbose;
commit = args->commit;
if (args->base && plen > 0 && args->base[plen - 1] == '/') { if (args->base && plen > 0 && args->base[plen - 1] == '/') {
char *base = xstrdup(args->base); char *base = xstrdup(args->base);

View File

@ -8,6 +8,7 @@ struct archiver_args {
const char *base; const char *base;
struct tree *tree; struct tree *tree;
const unsigned char *commit_sha1; const unsigned char *commit_sha1;
const struct commit *commit;
time_t time; time_t time;
const char **pathspec; const char **pathspec;
unsigned int verbose : 1; unsigned int verbose : 1;
@ -42,4 +43,6 @@ extern int write_tar_archive(struct archiver_args *);
extern int write_zip_archive(struct archiver_args *); extern int write_zip_archive(struct archiver_args *);
extern void *parse_extra_zip_args(int argc, const char **argv); extern void *parse_extra_zip_args(int argc, const char **argv);
extern void *sha1_file_to_archive(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size, const struct commit *commit);
#endif /* ARCHIVE_H */ #endif /* ARCHIVE_H */

View File

@ -10,6 +10,7 @@
#include "exec_cmd.h" #include "exec_cmd.h"
#include "pkt-line.h" #include "pkt-line.h"
#include "sideband.h" #include "sideband.h"
#include "attr.h"
static const char archive_usage[] = \ static const char archive_usage[] = \
"git-archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]"; "git-archive --format=<fmt> [--prefix=<prefix>/] [--verbose] [<extra>] <tree-ish> [path...]";
@ -80,6 +81,100 @@ static int run_remote_archiver(const char *remote, int argc,
return !!rv; return !!rv;
} }
static void *format_subst(const struct commit *commit, const char *format,
unsigned long *sizep)
{
unsigned long len = *sizep, result_len = 0;
const char *a = format;
char *result = NULL;
for (;;) {
const char *b, *c;
char *fmt, *formatted = NULL;
unsigned long a_len, fmt_len, formatted_len, allocated = 0;
b = memmem(a, len, "$Format:", 8);
if (!b || a + len < b + 9)
break;
c = memchr(b + 8, '$', len - 8);
if (!c)
break;
a_len = b - a;
fmt_len = c - b - 8;
fmt = xmalloc(fmt_len + 1);
memcpy(fmt, b + 8, fmt_len);
fmt[fmt_len] = '\0';
formatted_len = format_commit_message(commit, fmt, &formatted,
&allocated);
free(fmt);
result = xrealloc(result, result_len + a_len + formatted_len);
memcpy(result + result_len, a, a_len);
memcpy(result + result_len + a_len, formatted, formatted_len);
result_len += a_len + formatted_len;
len -= c + 1 - a;
a = c + 1;
}
if (result && len) {
result = xrealloc(result, result_len + len);
memcpy(result + result_len, a, len);
result_len += len;
}
*sizep = result_len;
return result;
}
static void *convert_to_archive(const char *path,
const void *src, unsigned long *sizep,
const struct commit *commit)
{
static struct git_attr *attr_export_subst;
struct git_attr_check check[1];
if (!commit)
return NULL;
if (!attr_export_subst)
attr_export_subst = git_attr("export-subst", 12);
check[0].attr = attr_export_subst;
if (git_checkattr(path, ARRAY_SIZE(check), check))
return NULL;
if (!ATTR_TRUE(check[0].value))
return NULL;
return format_subst(commit, src, sizep);
}
void *sha1_file_to_archive(const char *path, const unsigned char *sha1,
unsigned int mode, enum object_type *type,
unsigned long *size,
const struct commit *commit)
{
void *buffer, *converted;
buffer = read_sha1_file(sha1, type, size);
if (buffer && S_ISREG(mode)) {
converted = convert_to_working_tree(path, buffer, size);
if (converted) {
free(buffer);
buffer = converted;
}
converted = convert_to_archive(path, buffer, size, commit);
if (converted) {
free(buffer);
buffer = converted;
}
}
return buffer;
}
static int init_archiver(const char *name, struct archiver *ar) static int init_archiver(const char *name, struct archiver *ar)
{ {
int rv = -1, i; int rv = -1, i;
@ -109,7 +204,7 @@ void parse_treeish_arg(const char **argv, struct archiver_args *ar_args,
const unsigned char *commit_sha1; const unsigned char *commit_sha1;
time_t archive_time; time_t archive_time;
struct tree *tree; struct tree *tree;
struct commit *commit; const struct commit *commit;
unsigned char sha1[20]; unsigned char sha1[20];
if (get_sha1(name, sha1)) if (get_sha1(name, sha1))
@ -142,6 +237,7 @@ void parse_treeish_arg(const char **argv, struct archiver_args *ar_args,
} }
ar_args->tree = tree; ar_args->tree = tree;
ar_args->commit_sha1 = commit_sha1; ar_args->commit_sha1 = commit_sha1;
ar_args->commit = commit;
ar_args->time = archive_time; ar_args->time = archive_time;
} }

View File

@ -9,7 +9,7 @@
static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]"; static const char push_usage[] = "git-push [--all] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]";
static int all, force, thin = 1, verbose; static int all, force, thin, verbose;
static const char *receivepack; static const char *receivepack;
static const char **refspec; static const char **refspec;

View File

@ -200,6 +200,10 @@ static ssize_t do_sign(char *buffer, size_t size, size_t max)
bracket[1] = '\0'; bracket[1] = '\0';
} }
/* When the username signingkey is bad, program could be terminated
* because gpg exits without reading and then write gets SIGPIPE. */
signal(SIGPIPE, SIG_IGN);
memset(&gpg, 0, sizeof(gpg)); memset(&gpg, 0, sizeof(gpg));
gpg.argv = args; gpg.argv = args;
gpg.in = -1; gpg.in = -1;
@ -212,12 +216,17 @@ static ssize_t do_sign(char *buffer, size_t size, size_t max)
if (start_command(&gpg)) if (start_command(&gpg))
return error("could not run gpg."); return error("could not run gpg.");
write_or_die(gpg.in, buffer, size); if (write_in_full(gpg.in, buffer, size) != size) {
close(gpg.in);
finish_command(&gpg);
return error("gpg did not accept the tag data");
}
close(gpg.in); close(gpg.in);
gpg.close_in = 0; gpg.close_in = 0;
len = read_in_full(gpg.out, buffer + size, max - size); len = read_in_full(gpg.out, buffer + size, max - size);
finish_command(&gpg); if (finish_command(&gpg) || !len || len < 0)
return error("gpg failed to sign the tag");
if (len == max - size) if (len == max - size)
return error("could not read the entire signature from gpg."); return error("could not read the entire signature from gpg.");
@ -310,9 +319,10 @@ static void create_tag(const unsigned char *object, const char *tag,
size += header_len; size += header_len;
if (sign) { if (sign) {
size = do_sign(buffer, size, max_size); ssize_t r = do_sign(buffer, size, max_size);
if (size < 0) if (r < 0)
die("unable to sign the tag"); die("unable to sign the tag");
size = r;
} }
if (write_sha1_file(buffer, size, tag_type, result) < 0) if (write_sha1_file(buffer, size, tag_type, result) < 0)

View File

@ -592,7 +592,6 @@ extern void trace_argv_printf(const char **argv, int count, const char *format,
/* convert.c */ /* convert.c */
extern char *convert_to_git(const char *path, const char *src, unsigned long *sizep); extern char *convert_to_git(const char *path, const char *src, unsigned long *sizep);
extern char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep); extern char *convert_to_working_tree(const char *path, const char *src, unsigned long *sizep);
extern void *convert_sha1_file(const char *path, const unsigned char *sha1, unsigned int mode, enum object_type *type, unsigned long *size);
/* diff.c */ /* diff.c */
extern int diff_auto_refresh_index; extern int diff_auto_refresh_index;

View File

@ -787,8 +787,8 @@ static void fill_person(struct interp *table, const char *msg, int len)
interp_set_entry(table, 6, show_date(date, tz, DATE_ISO8601)); interp_set_entry(table, 6, show_date(date, tz, DATE_ISO8601));
} }
static long format_commit_message(const struct commit *commit, long format_commit_message(const struct commit *commit, const void *format,
const char *msg, char **buf_p, unsigned long *space_p) char **buf_p, unsigned long *space_p)
{ {
struct interp table[] = { struct interp table[] = {
{ "%H" }, /* commit hash */ { "%H" }, /* commit hash */
@ -843,6 +843,7 @@ static long format_commit_message(const struct commit *commit,
char parents[1024]; char parents[1024];
int i; int i;
enum { HEADER, SUBJECT, BODY } state; enum { HEADER, SUBJECT, BODY } state;
const char *msg = commit->buffer;
if (ILEFT_RIGHT + 1 != ARRAY_SIZE(table)) if (ILEFT_RIGHT + 1 != ARRAY_SIZE(table))
die("invalid interp table!"); die("invalid interp table!");
@ -924,7 +925,7 @@ static long format_commit_message(const struct commit *commit,
char *buf = *buf_p; char *buf = *buf_p;
unsigned long space = *space_p; unsigned long space = *space_p;
space = interpolate(buf, space, user_format, space = interpolate(buf, space, format,
table, ARRAY_SIZE(table)); table, ARRAY_SIZE(table));
if (!space) if (!space)
break; break;
@ -1165,7 +1166,7 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
char *buf; char *buf;
if (fmt == CMIT_FMT_USERFORMAT) if (fmt == CMIT_FMT_USERFORMAT)
return format_commit_message(commit, msg, buf_p, space_p); return format_commit_message(commit, user_format, buf_p, space_p);
encoding = (git_log_output_encoding encoding = (git_log_output_encoding
? git_log_output_encoding ? git_log_output_encoding

View File

@ -61,6 +61,7 @@ enum cmit_fmt {
}; };
extern enum cmit_fmt get_commit_format(const char *arg); extern enum cmit_fmt get_commit_format(const char *arg);
extern long format_commit_message(const struct commit *commit, const void *template, char **buf_p, unsigned long *space_p);
extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *, unsigned long len, char **buf_p, unsigned long *space_p, int abbrev, const char *subject, const char *after_subject, enum date_mode dmode); extern unsigned long pretty_print_commit(enum cmit_fmt fmt, const struct commit *, unsigned long len, char **buf_p, unsigned long *space_p, int abbrev, const char *subject, const char *after_subject, enum date_mode dmode);
/** Removes the first commit from a list sorted by date, and adds all /** Removes the first commit from a list sorted by date, and adds all

29
compat/memmem.c Normal file
View File

@ -0,0 +1,29 @@
#include "../git-compat-util.h"
void *gitmemmem(const void *haystack, size_t haystack_len,
const void *needle, size_t needle_len)
{
const char *begin = haystack;
const char *last_possible = begin + haystack_len - needle_len;
/*
* The first occurrence of the empty string is deemed to occur at
* the beginning of the string.
*/
if (needle_len == 0)
return (void *)begin;
/*
* Sanity check, otherwise the loop might search through the whole
* memory.
*/
if (haystack_len < needle_len)
return NULL;
for (; begin <= last_possible; begin++) {
if (!memcmp(begin, needle, needle_len))
return (void *)begin;
}
return NULL;
}

View File

@ -687,18 +687,3 @@ char *convert_to_working_tree(const char *path, const char *src, unsigned long *
return buf; return buf;
} }
void *convert_sha1_file(const char *path, const unsigned char *sha1,
unsigned int mode, enum object_type *type,
unsigned long *size)
{
void *buffer = read_sha1_file(sha1, type, size);
if (S_ISREG(mode) && buffer) {
void *converted = convert_to_working_tree(path, buffer, size);
if (converted) {
free(buffer);
buffer = converted;
}
}
return buffer;
}

21
diff.c
View File

@ -3135,6 +3135,22 @@ static void diffcore_apply_filter(const char *filter)
*q = outq; *q = outq;
} }
/* Check whether two filespecs with the same mode and size are identical */
static int diff_filespec_is_identical(struct diff_filespec *one,
struct diff_filespec *two)
{
if (S_ISGITLINK(one->mode)) {
diff_fill_sha1_info(one);
diff_fill_sha1_info(two);
return !hashcmp(one->sha1, two->sha1);
}
if (diff_populate_filespec(one, 0))
return 0;
if (diff_populate_filespec(two, 0))
return 0;
return !memcmp(one->data, two->data, one->size);
}
static void diffcore_skip_stat_unmatch(struct diff_options *diffopt) static void diffcore_skip_stat_unmatch(struct diff_options *diffopt)
{ {
int i; int i;
@ -3166,10 +3182,7 @@ static void diffcore_skip_stat_unmatch(struct diff_options *diffopt)
diff_populate_filespec(p->one, 1) || diff_populate_filespec(p->one, 1) ||
diff_populate_filespec(p->two, 1) || diff_populate_filespec(p->two, 1) ||
(p->one->size != p->two->size) || (p->one->size != p->two->size) ||
!diff_filespec_is_identical(p->one, p->two)) /* (2) */
diff_populate_filespec(p->one, 0) || /* (2) */
diff_populate_filespec(p->two, 0) ||
memcmp(p->one->data, p->two->data, p->one->size))
diff_q(&outq, p); diff_q(&outq, p);
else { else {
/* /*

View File

@ -172,6 +172,12 @@ extern uintmax_t gitstrtoumax(const char *, char **, int);
extern const char *githstrerror(int herror); extern const char *githstrerror(int herror);
#endif #endif
#ifdef NO_MEMMEM
#define memmem gitmemmem
void *gitmemmem(const void *haystack, size_t haystacklen,
const void *needle, size_t needlelen);
#endif
extern void release_pack_memory(size_t, int); extern void release_pack_memory(size_t, int);
static inline char* xstrdup(const char *str) static inline char* xstrdup(const char *str)

View File

@ -779,7 +779,7 @@ sub commit {
$xtag =~ tr/_/\./ if ( $opt_u ); $xtag =~ tr/_/\./ if ( $opt_u );
$xtag =~ s/[\/]/$opt_s/g; $xtag =~ s/[\/]/$opt_s/g;
system('git-tag', $xtag, $cid) == 0 system('git-tag', '-f', $xtag, $cid) == 0
or die "Cannot create tag $xtag: $!\n"; or die "Cannot create tag $xtag: $!\n";
print "Created tag '$xtag' on '$branch'\n" if $opt_v; print "Created tag '$xtag' on '$branch'\n" if $opt_v;

View File

@ -216,9 +216,11 @@ do
-v|--verbose) -v|--verbose)
verbose=t verbose=t
;; ;;
--whitespace=*)
git_am_opt="$git_am_opt $1"
;;
-C*) -C*)
git_am_opt=$1 git_am_opt="$git_am_opt $1"
shift
;; ;;
-*) -*)
usage usage

View File

@ -841,14 +841,9 @@ sub working_head_info {
sub read_commit_parents { sub read_commit_parents {
my ($parents, $c) = @_; my ($parents, $c) = @_;
my ($fh, $ctx) = command_output_pipe(qw/cat-file commit/, $c); chomp(my $p = command_oneline(qw/rev-list --parents -1/, $c));
while (<$fh>) { $p =~ s/^($c)\s*// or die "rev-list --parents -1 $c failed!\n";
chomp; @{$parents->{$c}} = split(/ /, $p);
last if '';
/^parent ($sha1)/ or next;
push @{$parents->{$c}}, $1;
}
close $fh; # break the pipe
} }
sub linearize_history { sub linearize_history {
@ -3013,7 +3008,7 @@ package Git::SVN::Ra;
use vars qw/@ISA $config_dir $_log_window_size/; use vars qw/@ISA $config_dir $_log_window_size/;
use strict; use strict;
use warnings; use warnings;
my ($can_do_switch, %ignored_err, $RA); my ($ra_invalid, $can_do_switch, %ignored_err, $RA);
BEGIN { BEGIN {
# enforce temporary pool usage for some simple functions # enforce temporary pool usage for some simple functions
@ -3174,7 +3169,11 @@ sub gs_do_switch {
$self->{url} = $full_url; $self->{url} = $full_url;
$reparented = 1; $reparented = 1;
} else { } else {
$_[0] = undef;
$self = undef;
$RA = undef;
$ra = Git::SVN::Ra->new($full_url); $ra = Git::SVN::Ra->new($full_url);
$ra_invalid = 1;
} }
} }
$ra ||= $self; $ra ||= $self;
@ -3234,6 +3233,7 @@ sub gs_fetch_loop_common {
my $inc = $_log_window_size; my $inc = $_log_window_size;
my ($min, $max) = ($base, $head < $base + $inc ? $head : $base + $inc); my ($min, $max) = ($base, $head < $base + $inc ? $head : $base + $inc);
my $longest_path = longest_common_path($gsv, $globs); my $longest_path = longest_common_path($gsv, $globs);
my $ra_url = $self->{url};
while (1) { while (1) {
my %revs; my %revs;
my $err; my $err;
@ -3295,6 +3295,13 @@ sub gs_fetch_loop_common {
"$g->{t}-maxRev"; "$g->{t}-maxRev";
Git::SVN::tmp_config($k, $r); Git::SVN::tmp_config($k, $r);
} }
if ($ra_invalid) {
$_[0] = undef;
$self = undef;
$RA = undef;
$self = Git::SVN::Ra->new($ra_url);
$ra_invalid = undef;
}
} }
# pre-fill the .rev_db since it'll eventually get filled in # pre-fill the .rev_db since it'll eventually get filled in
# with '0' x40 if something new gets committed # with '0' x40 if something new gets committed

View File

@ -873,7 +873,7 @@ sub commit {
$dest =~ tr/_/\./ if $opt_u; $dest =~ tr/_/\./ if $opt_u;
system('git-tag', $dest, $cid) == 0 system('git-tag', '-f', $dest, $cid) == 0
or die "Cannot create tag $dest: $!\n"; or die "Cannot create tag $dest: $!\n";
print "Created tag '$dest' on '$branch'\n" if $opt_v; print "Created tag '$dest' on '$branch'\n" if $opt_v;

View File

@ -28,12 +28,15 @@ commit id embedding:
TAR=${TAR:-tar} TAR=${TAR:-tar}
UNZIP=${UNZIP:-unzip} UNZIP=${UNZIP:-unzip}
SUBSTFORMAT=%H%n
test_expect_success \ test_expect_success \
'populate workdir' \ 'populate workdir' \
'mkdir a b c && 'mkdir a b c &&
echo simple textfile >a/a && echo simple textfile >a/a &&
mkdir a/bin && mkdir a/bin &&
cp /bin/sh a/bin && cp /bin/sh a/bin &&
printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile &&
ln -s a a/l1 && ln -s a a/l1 &&
(p=long_path_to_a_file && cd a && (p=long_path_to_a_file && cd a &&
for depth in 1 2 3 4 5; do mkdir $p && cd $p; done && for depth in 1 2 3 4 5; do mkdir $p && cd $p; done &&
@ -104,6 +107,22 @@ test_expect_success \
'validate file contents with prefix' \ 'validate file contents with prefix' \
'diff -r a c/prefix/a' 'diff -r a c/prefix/a'
test_expect_success \
'create an archive with a substfile' \
'echo substfile export-subst >a/.gitattributes &&
git archive HEAD >f.tar &&
rm a/.gitattributes'
test_expect_success \
'extract substfile' \
'(mkdir f && cd f && $TAR xf -) <f.tar'
test_expect_success \
'validate substfile contents' \
'git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
>f/a/substfile.expected &&
diff f/a/substfile.expected f/a/substfile'
test_expect_success \ test_expect_success \
'git archive --format=zip' \ 'git archive --format=zip' \
'git archive --format=zip HEAD >d.zip' 'git archive --format=zip HEAD >d.zip'

View File

@ -990,6 +990,13 @@ test_expect_success \
git diff expect actual git diff expect actual
' '
# try to sign with bad user.signingkey
git config user.signingkey BobTheMouse
test_expect_failure \
'git-tag -s fails if gpg is misconfigured' \
'git tag -s -m tail tag-gpg-failure'
git config --unset user.signingkey
# try to verify without gpg: # try to verify without gpg:
rm -rf gpghome rm -rf gpghome

View File

@ -152,6 +152,10 @@ test_expect_success 'the --cached sha1 should be rev1' '
git-submodule --cached status | grep "^+$rev1" git-submodule --cached status | grep "^+$rev1"
' '
test_expect_success 'git diff should report the SHA1 of the new submodule commit' '
git-diff | grep "^+Subproject commit $rev2"
'
test_expect_success 'update should checkout rev1' ' test_expect_success 'update should checkout rev1' '
git-submodule update && git-submodule update &&
head=$(cd lib && git rev-parse HEAD) && head=$(cd lib && git rev-parse HEAD) &&