Merge branch 'jc/bindiff' into next

* jc/bindiff:
  binary diff: further updates.
  binary patch.
  pack-object: squelch eye-candy on non-tty
  core.prefersymlinkrefs: use symlinks for .git/HEAD
  repo-config: trim white-space before comment
  Fix for config file section parsing.
  Clarify git-cherry documentation.
  Update git-unpack-objects documentation.
  Fix up docs where "--" isn't displayed correctly.
  Several trivial documentation touch ups.
  git-svn 1.0.0
  git-svn: documentation updates
  delta: stricter constness
  Makefile: do not link rev-list any specially.
  builtin-push: --all and --tags _are_ explicit refspecs
This commit is contained in:
Junio C Hamano 2006-05-05 15:36:04 -07:00
commit 2749fa7771
31 changed files with 585 additions and 123 deletions

View File

@ -26,7 +26,7 @@ OPTIONS
-v::
Be verbose.
--::
\--::
This option can be used to separate command-line options from
the list of files, (useful when filenames might be mistaken
for command-line options).

View File

@ -63,7 +63,7 @@ OPTIONS
Only meaningful with `--stdin`; paths are separated with
NUL character instead of LF.
--::
\--::
Do not interpret any more arguments as options.
The order of the flags used to matter, but not anymore.

View File

@ -11,11 +11,20 @@ SYNOPSIS
DESCRIPTION
-----------
Each commit between the fork-point and <head> is examined, and compared against
the change each commit between the fork-point and <upstream> introduces.
Commits already included in upstream are prefixed with '-' (meaning "drop from
my local pull"), while commits missing from upstream are prefixed with '+'
(meaning "add to the updated upstream").
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
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.
Because git-cherry compares the changeset rather than the commit id
(sha1), you can use git-cherry to find out if a commit you made locally
has been applied <upstream> under a different commit id. For example,
this will happen if you're feeding patches <upstream> via email rather
than pushing or pulling commits directly.
OPTIONS
-------

View File

@ -101,7 +101,7 @@ OPTIONS
is not allowed.
Examples
~~~~~~~~
--------
Clone from upstream::
+

View File

@ -106,7 +106,7 @@ but can be used to amend a merge commit.
index and the latest commit does not match on the
specified paths to avoid confusion.
--::
\--::
Do not interpret any more arguments as options.
<file>...::

View File

@ -29,6 +29,7 @@ CONFIGURATION
git-imap-send requires the following values in the repository
configuration file (shown with examples):
..........................
[imap]
Folder = "INBOX.Drafts"
@ -38,8 +39,9 @@ configuration file (shown with examples):
[imap]
Host = imap.server.com
User = bob
Password = pwd
Pass = pwd
Port = 143
..........................
BUGS

View File

@ -51,7 +51,7 @@ git log v2.6.12.. include/scsi drivers/scsi::
Show all commits since version 'v2.6.12' that changed any file
in the include/scsi or drivers/scsi subdirectories
git log --since="2 weeks ago" -- gitk::
git log --since="2 weeks ago" \-- gitk::
Show the changes during the last two weeks to the file 'gitk'.
The "--" is necessary to avoid confusion with the *branch* named

View File

@ -106,7 +106,7 @@ OPTIONS
lines, show only handful hexdigits prefix.
Non default number of digits can be specified with --abbrev=<n>.
--::
\--::
Do not interpret any more arguments as options.
<file>::

View File

@ -8,7 +8,7 @@ git-merge-index - Runs a merge for files needing merging
SYNOPSIS
--------
'git-merge-index' [-o] [-q] <merge-program> (-a | -- | <file>\*)
'git-merge-index' [-o] [-q] <merge-program> (-a | \-- | <file>\*)
DESCRIPTION
-----------
@ -19,7 +19,7 @@ files are passed as arguments 5, 6 and 7.
OPTIONS
-------
--::
\--::
Do not interpret any more arguments as options.
-a::

View File

@ -41,6 +41,7 @@ Enter git-name-rev:
------------
% git name-rev 33db5f4d9027a10e477ccf054b2c1ab94f74c85a
33db5f4d9027a10e477ccf054b2c1ab94f74c85a tags/v0.99^0~940
------------
Now you are wiser, because you know that it happened 940 revisions before v0.99.

View File

@ -28,7 +28,7 @@ OPTIONS
Do not remove anything; just report what it would
remove.
--::
\--::
Do not interpret any more arguments as options.
<head>...::

View File

@ -38,6 +38,7 @@ OPTIONS
-d::
After packing, if the newly created packs make some
existing packs redundant, remove the redundant packs.
Also runs gitlink:git-prune-packed[1].
-l::
Pass the `--local` option to `git pack-objects`, see

View File

@ -34,10 +34,10 @@ convert the value to the canonical form (simple decimal number for int,
a "true" or "false" string for bool). If no type specifier is passed,
no checks or transformations are performed on the value.
This command will fail if
This command will fail if:
. .git/config is invalid,
. .git/config can not be written to,
. The .git/config file is invalid,
. Can not write to .git/config,
. no section was provided,
. the section or key is invalid,
. you try to unset an option which does not exist, or

View File

@ -43,7 +43,7 @@ OPTIONS
Commit to make the current HEAD.
Examples
~~~~~~~~
--------
Undo a commit and redo::
+

View File

@ -32,7 +32,7 @@ OPTIONS
-v::
Be verbose.
--::
\--::
This option can be used to separate command-line options from
the list of files, (useful when filenames might be mistaken
for command-line options).

View File

@ -13,9 +13,16 @@ SYNOPSIS
DESCRIPTION
-----------
Reads a packed archive (.pack) from the standard input, and
expands the objects contained in the pack into "one-file
one-object" format in $GIT_OBJECT_DIRECTORY.
Read a packed archive (.pack) from the standard input, expanding
the objects contained within and writing them into the repository in
"loose" (one object per file) format.
Objects that already exist in the repository will *not* be unpacked
from the pack-file. Therefore, nothing will be unpacked if you use
this command on a pack-file that exists within the target repository.
Please see the `git-repack` documentation for options to generate
new packs and replace existing ones.
OPTIONS
-------

View File

@ -113,7 +113,7 @@ OPTIONS
Only meaningful with `--stdin`; paths are separated with
NUL character instead of LF.
--::
\--::
Do not interpret any more arguments as options.
<file>::

View File

@ -25,7 +25,7 @@ OPTIONS
-v::
After verifying the pack, show list of objects contained
in the pack.
--::
\--::
Do not interpret any more arguments as options.
OUTPUT FORMAT

View File

@ -58,7 +58,7 @@ git-whatchanged -p v2.6.12.. include/scsi drivers/scsi::
Show as patches the commits since version 'v2.6.12' that changed
any file in the include/scsi or drivers/scsi subdirectories
git-whatchanged --since="2 weeks ago" -- gitk::
git-whatchanged --since="2 weeks ago" \-- gitk::
Show the changes during the last two weeks to the file 'gitk'.
The "--" is necessary to avoid confusion with the *branch* named

View File

@ -31,7 +31,7 @@ gitk v2.6.12.. include/scsi drivers/scsi::
Show as the changes since version 'v2.6.12' that changed any
file in the include/scsi or drivers/scsi subdirectories
gitk --since="2 weeks ago" -- gitk::
gitk --since="2 weeks ago" \-- gitk::
Show the changes during the last two weeks to the file 'gitk'.
The "--" is necessary to avoid confusion with the *branch* named

View File

@ -205,7 +205,7 @@ DIFF_OBJS = \
diffcore-delta.o log-tree.o
LIB_OBJS = \
blob.o commit.o connect.o csum-file.o cache-tree.o \
blob.o commit.o connect.o csum-file.o cache-tree.o base85.o \
date.o diff-delta.o entry.o exec_cmd.o ident.o index.o \
object.o pack-check.o patch-delta.o path.o pkt-line.o \
quote.o read-cache.o refs.o run-command.o \
@ -565,10 +565,6 @@ git-http-push$X: revision.o http.o http-push.o $(LIB_FILE)
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
git-rev-list$X: rev-list.o $(LIB_FILE)
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIBS) $(OPENSSL_LIBSSL)
init-db.o: init-db.c
$(CC) -c $(ALL_CFLAGS) \
-DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c

210
apply.c
View File

@ -11,6 +11,7 @@
#include "cache-tree.h"
#include "quote.h"
#include "blob.h"
#include "delta.h"
// --check turns on checking that the working tree matches the
// files that are being modified, but doesn't apply the patch
@ -114,6 +115,9 @@ struct patch {
char *new_name, *old_name, *def_name;
unsigned int old_mode, new_mode;
int is_rename, is_copy, is_new, is_delete, is_binary;
#define BINARY_DELTA_DEFLATED 1
#define BINARY_LITERAL_DEFLATED 2
unsigned long deflate_origlen;
int lines_added, lines_deleted;
int score;
struct fragment *fragments;
@ -967,6 +971,88 @@ static inline int metadata_changes(struct patch *patch)
patch->old_mode != patch->new_mode);
}
static int parse_binary(char *buffer, unsigned long size, struct patch *patch)
{
/* We have read "GIT binary patch\n"; what follows is a line
* that says the patch method (currently, either "deflated
* literal" or "deflated delta") and the length of data before
* deflating; a sequence of 'length-byte' followed by base-85
* encoded data follows.
*
* Each 5-byte sequence of base-85 encodes up to 4 bytes,
* and we would limit the patch line to 66 characters,
* so one line can fit up to 13 groups that would decode
* to 52 bytes max. The length byte 'A'-'Z' corresponds
* to 1-26 bytes, and 'a'-'z' corresponds to 27-52 bytes.
* The end of binary is signalled with an empty line.
*/
int llen, used;
struct fragment *fragment;
char *data = NULL;
patch->fragments = fragment = xcalloc(1, sizeof(*fragment));
/* Grab the type of patch */
llen = linelen(buffer, size);
used = llen;
linenr++;
if (!strncmp(buffer, "delta ", 6)) {
patch->is_binary = BINARY_DELTA_DEFLATED;
patch->deflate_origlen = strtoul(buffer + 6, NULL, 10);
}
else if (!strncmp(buffer, "literal ", 8)) {
patch->is_binary = BINARY_LITERAL_DEFLATED;
patch->deflate_origlen = strtoul(buffer + 8, NULL, 10);
}
else
return error("unrecognized binary patch at line %d: %.*s",
linenr-1, llen-1, buffer);
buffer += llen;
while (1) {
int byte_length, max_byte_length, newsize;
llen = linelen(buffer, size);
used += llen;
linenr++;
if (llen == 1)
break;
/* Minimum line is "A00000\n" which is 7-byte long,
* and the line length must be multiple of 5 plus 2.
*/
if ((llen < 7) || (llen-2) % 5)
goto corrupt;
max_byte_length = (llen - 2) / 5 * 4;
byte_length = *buffer;
if ('A' <= byte_length && byte_length <= 'Z')
byte_length = byte_length - 'A' + 1;
else if ('a' <= byte_length && byte_length <= 'z')
byte_length = byte_length - 'a' + 27;
else
goto corrupt;
/* if the input length was not multiple of 4, we would
* have filler at the end but the filler should never
* exceed 3 bytes
*/
if (max_byte_length < byte_length ||
byte_length <= max_byte_length - 4)
goto corrupt;
newsize = fragment->size + byte_length;
data = xrealloc(data, newsize);
if (decode_85(data + fragment->size,
buffer + 1,
byte_length))
goto corrupt;
fragment->size = newsize;
buffer += llen;
size -= llen;
}
fragment->patch = data;
return used;
corrupt:
return error("corrupt binary patch at line %d: %.*s",
linenr-1, llen-1, buffer);
}
static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
{
int hdrsize, patchsize;
@ -983,19 +1069,34 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
"Files ",
NULL,
};
static const char git_binary[] = "GIT binary patch\n";
int i;
int hd = hdrsize + offset;
unsigned long llen = linelen(buffer + hd, size - hd);
if (!memcmp(" differ\n", buffer + hd + llen - 8, 8))
if (llen == sizeof(git_binary) - 1 &&
!memcmp(git_binary, buffer + hd, llen)) {
int used;
linenr++;
used = parse_binary(buffer + hd + llen,
size - hd - llen, patch);
if (used)
patchsize = used + llen;
else
patchsize = 0;
}
else if (!memcmp(" differ\n", buffer + hd + llen - 8, 8)) {
for (i = 0; binhdr[i]; i++) {
int len = strlen(binhdr[i]);
if (len < size - hd &&
!memcmp(binhdr[i], buffer + hd, len)) {
linenr++;
patch->is_binary = 1;
patchsize = llen;
break;
}
}
}
/* Empty patch cannot be applied if:
* - it is a binary patch and we do not do binary_replace, or
@ -1346,13 +1447,67 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag)
return offset;
}
static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
static char *inflate_it(const void *data, unsigned long size,
unsigned long inflated_size)
{
struct fragment *frag = patch->fragments;
const char *name = patch->old_name ? patch->old_name : patch->new_name;
z_stream stream;
void *out;
int st;
if (patch->is_binary) {
memset(&stream, 0, sizeof(stream));
stream.next_in = (unsigned char *)data;
stream.avail_in = size;
stream.next_out = out = xmalloc(inflated_size);
stream.avail_out = inflated_size;
inflateInit(&stream);
st = inflate(&stream, Z_FINISH);
if ((st != Z_STREAM_END) || stream.total_out != inflated_size) {
free(out);
return NULL;
}
return out;
}
static int apply_binary_fragment(struct buffer_desc *desc, struct patch *patch)
{
unsigned long dst_size;
struct fragment *fragment = patch->fragments;
void *data;
void *result;
data = inflate_it(fragment->patch, fragment->size,
patch->deflate_origlen);
if (!data)
return error("corrupt patch data");
switch (patch->is_binary) {
case BINARY_DELTA_DEFLATED:
result = patch_delta(desc->buffer, desc->size,
data,
patch->deflate_origlen,
&dst_size);
free(desc->buffer);
desc->buffer = result;
free(data);
break;
case BINARY_LITERAL_DEFLATED:
free(desc->buffer);
desc->buffer = data;
dst_size = patch->deflate_origlen;
break;
}
if (!desc->buffer)
return -1;
desc->size = desc->alloc = dst_size;
return 0;
}
static int apply_binary(struct buffer_desc *desc, struct patch *patch)
{
const char *name = patch->old_name ? patch->old_name : patch->new_name;
unsigned char sha1[20];
unsigned char hdr[50];
int hdrlen;
if (!allow_binary_replacement)
return error("cannot apply binary patch to '%s' "
@ -1370,9 +1525,6 @@ static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
"without full index line", name);
if (patch->old_name) {
unsigned char hdr[50];
int hdrlen;
/* See if the old one matches what the patch
* applies to.
*/
@ -1391,31 +1543,54 @@ static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
"'%s' but it is not empty", name);
}
/* For now, we do not record post-image data in the patch,
* and require the object already present in the recipient's
* object database.
*/
if (desc->buffer) {
get_sha1_hex(patch->new_sha1_prefix, sha1);
if (!memcmp(sha1, null_sha1, 20)) {
free(desc->buffer);
desc->alloc = desc->size = 0;
desc->buffer = NULL;
return 0; /* deletion patch */
}
get_sha1_hex(patch->new_sha1_prefix, sha1);
if (memcmp(sha1, null_sha1, 20)) {
if (has_sha1_file(sha1)) {
/* We already have the postimage */
char type[10];
unsigned long size;
free(desc->buffer);
desc->buffer = read_sha1_file(sha1, type, &size);
if (!desc->buffer)
return error("the necessary postimage %s for "
"'%s' does not exist",
"'%s' cannot be read",
patch->new_sha1_prefix, name);
desc->alloc = desc->size = size;
}
else {
/* We have verified desc matches the preimage;
* apply the patch data to it, which is stored
* in the patch->fragments->{patch,size}.
*/
if (apply_binary_fragment(desc, patch))
return error("binary patch does not apply to '%s'",
name);
/* verify that the result matches */
write_sha1_file_prepare(desc->buffer, desc->size, blob_type,
sha1, hdr, &hdrlen);
if (strcmp(sha1_to_hex(sha1), patch->new_sha1_prefix))
return error("binary patch to '%s' creates incorrect result", name);
}
return 0;
}
static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
{
struct fragment *frag = patch->fragments;
const char *name = patch->old_name ? patch->old_name : patch->new_name;
if (patch->is_binary)
return apply_binary(desc, patch);
while (frag) {
if (apply_one_fragment(desc, frag) < 0)
return error("patch failed: %s:%ld",
@ -1993,7 +2168,8 @@ int main(int argc, char **argv)
diffstat = 1;
continue;
}
if (!strcmp(arg, "--allow-binary-replacement")) {
if (!strcmp(arg, "--allow-binary-replacement") ||
!strcmp(arg, "--binary")) {
allow_binary_replacement = 1;
continue;
}

134
base85.c Normal file
View File

@ -0,0 +1,134 @@
#include "cache.h"
#undef DEBUG_85
#ifdef DEBUG_85
#define say(a) fprintf(stderr, a)
#define say1(a,b) fprintf(stderr, a, b)
#define say2(a,b,c) fprintf(stderr, a, b, c)
#else
#define say(a) do {} while(0)
#define say1(a,b) do {} while(0)
#define say2(a,b,c) do {} while(0)
#endif
static const char en85[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
'U', 'V', 'W', 'X', 'Y', 'Z',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z',
'!', '#', '$', '%', '&', '(', ')', '*', '+', '-',
';', '<', '=', '>', '?', '@', '^', '_', '`', '{',
'|', '}', '~'
};
static char de85[256];
static void prep_base85(void)
{
int i;
if (de85['Z'])
return;
for (i = 0; i < ARRAY_SIZE(en85); i++) {
int ch = en85[i];
de85[ch] = i + 1;
}
}
int decode_85(char *dst, char *buffer, int len)
{
prep_base85();
say2("decode 85 <%.*s>", len/4*5, buffer);
while (len) {
unsigned acc = 0;
int cnt;
for (cnt = 0; cnt < 5; cnt++, buffer++) {
int ch = *((unsigned char *)buffer);
int de = de85[ch];
if (!de)
return error("invalid base85 alphabet %c", ch);
de--;
if (cnt == 4) {
/*
* Detect overflow. The largest
* 5-letter possible is "|NsC0" to
* encode 0xffffffff, and "|NsC" gives
* 0x03030303 at this point (i.e.
* 0xffffffff = 0x03030303 * 85).
*/
if (0x03030303 < acc ||
(0x03030303 == acc && de))
error("invalid base85 sequence %.5s",
buffer-3);
}
acc = acc * 85 + de;
say1(" <%08x>", acc);
}
say1(" %08x", acc);
for (cnt = 0; cnt < 4 && len; cnt++, len--) {
*dst++ = (acc >> 24) & 0xff;
acc = acc << 8;
}
}
say("\n");
return 0;
}
void encode_85(char *buf, unsigned char *data, int bytes)
{
prep_base85();
say("encode 85");
while (bytes) {
unsigned acc = 0;
int cnt;
for (cnt = 0; cnt < 4 && bytes; cnt++, bytes--) {
int ch = *data++;
acc |= ch << ((3-cnt)*8);
}
say1(" %08x", acc);
for (cnt = 0; cnt < 5; cnt++) {
int val = acc % 85;
acc /= 85;
buf[4-cnt] = en85[val];
}
buf += 5;
}
say("\n");
*buf = 0;
}
#ifdef DEBUG_85
int main(int ac, char **av)
{
char buf[1024];
if (!strcmp(av[1], "-e")) {
int len = strlen(av[2]);
encode_85(buf, av[2], len);
if (len <= 26) len = len + 'A' - 1;
else len = len + 'a' - 26 + 1;
printf("encoded: %c%s\n", len, buf);
return 0;
}
if (!strcmp(av[1], "-d")) {
int len = *av[2];
if ('A' <= len && len <= 'Z') len = len - 'A' + 1;
else len = len - 'a' + 26 + 1;
decode_85(buf, av[2]+1, len);
printf("decoded: %.*s\n", len, buf);
return 0;
}
if (!strcmp(av[1], "-t")) {
char t[4] = { -1,-1,-1,-1 };
encode_85(buf, t, 4);
printf("encoded: D%s\n", buf);
return 0;
}
}
#endif

View File

@ -72,7 +72,7 @@ static int get_remotes_uri(const char *repo, const char *uri[MAX_URI])
{
int n = 0;
FILE *f = fopen(git_path("remotes/%s", repo), "r");
int has_explicit_refspec = refspec_nr;
int has_explicit_refspec = refspec_nr || all || tags;
if (!f)
return -1;
@ -144,7 +144,7 @@ static int get_config_remotes_uri(const char *repo, const char *uri[MAX_URI])
config_repo = repo;
config_current_uri = 0;
config_uri = uri;
config_get_refspecs = !refspec_nr;
config_get_refspecs = !(refspec_nr || all || tags);
git_config(get_remote_config);
return config_current_uri;

View File

@ -365,4 +365,8 @@ extern int receive_keep_pack(int fd[2], const char *me, int quiet);
/* pager.c */
extern void setup_pager(void);
/* base85 */
int decode_85(char *dst, char *line, int linelen);
void encode_85(char *buf, unsigned char *data, int bytes);
#endif /* CACHE_H */

View File

@ -335,7 +335,8 @@ static int store_aux(const char* key, const char* value)
store.offset[store.seen] = ftell(config_file);
store.state = KEY_SEEN;
store.seen++;
} else if(!strncmp(key, store.key, store.baselen))
} else if (strrchr(key, '.') - key == store.baselen &&
!strncmp(key, store.key, store.baselen))
store.state = SECTION_SEEN;
}
return 0;

View File

@ -8,7 +8,7 @@ use vars qw/ $AUTHOR $VERSION
$GIT_SVN_INDEX $GIT_SVN
$GIT_DIR $REV_DIR/;
$AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
$VERSION = '0.11.0';
$VERSION = '1.0.0';
use Cwd qw/abs_path/;
$GIT_DIR = abs_path($ENV{GIT_DIR} || '.git');
@ -42,7 +42,8 @@ my %fc_opts = ( 'no-ignore-externals' => \$_no_ignore_ext,
my %cmd = (
fetch => [ \&fetch, "Download new revisions from SVN",
{ 'revision|r=s' => \$_revision, %fc_opts } ],
init => [ \&init, "Initialize and fetch (import)", { } ],
init => [ \&init, "Initialize a repo for tracking" .
" (requires URL argument)", { } ],
commit => [ \&commit, "Commit git revisions to SVN",
{ 'stdin|' => \$_stdin,
'edit|e' => \$_edit,
@ -220,7 +221,8 @@ when you have upgraded your tools and habits to use refs/remotes/$GIT_SVN
}
sub init {
$SVN_URL = shift or croak "SVN repository location required\n";
$SVN_URL = shift or die "SVN repository location required " .
"as a command-line argument\n";
unless (-d $GIT_DIR) {
sys('git-init-db');
}

View File

@ -36,17 +36,22 @@ COMMANDS
--------
init::
Creates an empty git repository with additional metadata
directories for git-svn. The SVN_URL must be specified
at this point.
directories for git-svn. The Subversion URL must be specified
as a command-line argument.
fetch::
Fetch unfetched revisions from the SVN_URL we are tracking.
refs/heads/remotes/git-svn will be updated to the latest revision.
Fetch unfetched revisions from the Subversion URL we are
tracking. refs/remotes/git-svn will be updated to the
latest revision.
Note: You should never attempt to modify the remotes/git-svn branch
outside of git-svn. Instead, create a branch from remotes/git-svn
and work on that branch. Use the 'commit' command (see below)
to write git commits back to remotes/git-svn.
Note: You should never attempt to modify the remotes/git-svn
branch outside of git-svn. Instead, create a branch from
remotes/git-svn and work on that branch. Use the 'commit'
command (see below) to write git commits back to
remotes/git-svn.
See 'Additional Fetch Arguments' if you are interested in
manually joining branches on commit.
commit::
Commit specified commit or tree objects to SVN. This relies on
@ -62,9 +67,9 @@ rebuild::
tracked with git-svn. Unfortunately, git-clone does not clone
git-svn metadata and the svn working tree that git-svn uses for
its operations. This rebuilds the metadata so git-svn can
resume fetch operations. SVN_URL may be optionally specified if
the directory/repository you're tracking has moved or changed
protocols.
resume fetch operations. A Subversion URL may be optionally
specified at the command-line if the directory/repository you're
tracking has moved or changed protocols.
show-ignore::
Recursively finds and lists the svn:ignore property on
@ -123,6 +128,24 @@ OPTIONS
repo-config key: svn.l
repo-config key: svn.findcopiesharder
-A<filename>::
--authors-file=<filename>::
Syntax is compatible with the files used by git-svnimport and
git-cvsimport:
------------------------------------------------------------------------
loginname = Joe User <user@example.com>
------------------------------------------------------------------------
If this option is specified and git-svn encounters an SVN
committer name that does not exist in the authors-file, git-svn
will abort operation. The user will then have to add the
appropriate entry. Re-running the previous git-svn command
after the authors-file is modified should continue operation.
repo-config key: svn.authors-file
ADVANCED OPTIONS
----------------
-b<refname>::

114
diff.c
View File

@ -8,6 +8,7 @@
#include "quote.h"
#include "diff.h"
#include "diffcore.h"
#include "delta.h"
#include "xdiff-interface.h"
static int use_size_cache;
@ -391,6 +392,90 @@ static void show_stats(struct diffstat_t* data)
total_files, adds, dels);
}
static unsigned char *deflate_it(char *data,
unsigned long size,
unsigned long *result_size)
{
int bound;
unsigned char *deflated;
z_stream stream;
memset(&stream, 0, sizeof(stream));
deflateInit(&stream, Z_BEST_COMPRESSION);
bound = deflateBound(&stream, size);
deflated = xmalloc(bound);
stream.next_out = deflated;
stream.avail_out = bound;
stream.next_in = (unsigned char *)data;
stream.avail_in = size;
while (deflate(&stream, Z_FINISH) == Z_OK)
; /* nothing */
deflateEnd(&stream);
*result_size = stream.total_out;
return deflated;
}
static void emit_binary_diff(mmfile_t *one, mmfile_t *two)
{
void *cp;
void *delta;
void *deflated;
void *data;
unsigned long orig_size;
unsigned long delta_size;
unsigned long deflate_size;
unsigned long data_size;
printf("GIT binary patch\n");
/* We could do deflated delta, or we could do just deflated two,
* whichever is smaller.
*/
delta = NULL;
deflated = deflate_it(two->ptr, two->size, &deflate_size);
if (one->size && two->size) {
delta = diff_delta(one->ptr, one->size,
two->ptr, two->size,
&delta_size, deflate_size);
if (delta) {
void *to_free = delta;
orig_size = delta_size;
delta = deflate_it(delta, delta_size, &delta_size);
free(to_free);
}
}
if (delta && delta_size < deflate_size) {
printf("delta %lu\n", orig_size);
free(deflated);
data = delta;
data_size = delta_size;
}
else {
printf("literal %lu\n", two->size);
free(delta);
data = deflated;
data_size = deflate_size;
}
/* emit data encoded in base85 */
cp = data;
while (data_size) {
int bytes = (52 < data_size) ? 52 : data_size;
char line[70];
data_size -= bytes;
if (bytes <= 26)
line[0] = bytes + 'A' - 1;
else
line[0] = bytes - 26 + 'a' - 1;
encode_85(line + 1, cp, bytes);
cp += bytes;
puts(line);
}
printf("\n");
free(data);
}
#define FIRST_FEW_BYTES 8000
static int mmfile_is_binary(mmfile_t *mf)
{
@ -407,6 +492,7 @@ static void builtin_diff(const char *name_a,
struct diff_filespec *one,
struct diff_filespec *two,
const char *xfrm_msg,
struct diff_options *o,
int complete_rewrite)
{
mmfile_t mf1, mf2;
@ -451,8 +537,17 @@ static void builtin_diff(const char *name_a,
if (fill_mmfile(&mf1, one) < 0 || fill_mmfile(&mf2, two) < 0)
die("unable to read files to diff");
if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2))
printf("Binary files %s and %s differ\n", lbl[0], lbl[1]);
if (mmfile_is_binary(&mf1) || mmfile_is_binary(&mf2)) {
/* Quite common confusing case */
if (mf1.size == mf2.size &&
!memcmp(mf1.ptr, mf2.ptr, mf1.size))
goto free_ab_and_return;
if (o->binary)
emit_binary_diff(&mf1, &mf2);
else
printf("Binary files %s and %s differ\n",
lbl[0], lbl[1]);
}
else {
/* Crazy xdl interfaces.. */
const char *diffopts = getenv("GIT_DIFF_OPTS");
@ -928,6 +1023,7 @@ static void run_diff_cmd(const char *pgm,
struct diff_filespec *one,
struct diff_filespec *two,
const char *xfrm_msg,
struct diff_options *o,
int complete_rewrite)
{
if (pgm) {
@ -937,7 +1033,7 @@ static void run_diff_cmd(const char *pgm,
}
if (one && two)
builtin_diff(name, other ? other : name,
one, two, xfrm_msg, complete_rewrite);
one, two, xfrm_msg, o, complete_rewrite);
else
printf("* Unmerged path %s\n", name);
}
@ -971,7 +1067,7 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
if (DIFF_PAIR_UNMERGED(p)) {
/* unmerged */
run_diff_cmd(pgm, p->one->path, NULL, NULL, NULL, NULL, 0);
run_diff_cmd(pgm, p->one->path, NULL, NULL, NULL, NULL, o, 0);
return;
}
@ -1041,14 +1137,14 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
* needs to be split into deletion and creation.
*/
struct diff_filespec *null = alloc_filespec(two->path);
run_diff_cmd(NULL, name, other, one, null, xfrm_msg, 0);
run_diff_cmd(NULL, name, other, one, null, xfrm_msg, o, 0);
free(null);
null = alloc_filespec(one->path);
run_diff_cmd(NULL, name, other, null, two, xfrm_msg, 0);
run_diff_cmd(NULL, name, other, null, two, xfrm_msg, o, 0);
free(null);
}
else
run_diff_cmd(pgm, name, other, one, two, xfrm_msg,
run_diff_cmd(pgm, name, other, one, two, xfrm_msg, o,
complete_rewrite);
free(name_munged);
@ -1147,6 +1243,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
options->rename_limit = strtoul(arg+2, NULL, 10);
else if (!strcmp(arg, "--full-index"))
options->full_index = 1;
else if (!strcmp(arg, "--binary")) {
options->output_format = DIFF_FORMAT_PATCH;
options->full_index = options->binary = 1;
}
else if (!strcmp(arg, "--name-only"))
options->output_format = DIFF_FORMAT_NAME;
else if (!strcmp(arg, "--name-status"))

1
diff.h
View File

@ -28,6 +28,7 @@ struct diff_options {
with_raw:1,
with_stat:1,
tree_in_recursive:1,
binary:1,
full_index:1,
silent_on_remove:1,
find_copies_harder:1;

View File

@ -1243,6 +1243,7 @@ int main(int argc, char **argv)
setup_git_directory();
progress = isatty(2);
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
@ -1273,6 +1274,10 @@ int main(int argc, char **argv)
usage(pack_usage);
continue;
}
if (!strcmp("--progress", arg)) {
progress = 1;
continue;
}
if (!strcmp("-q", arg)) {
progress = 0;
continue;