diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Documentation/Makefile | 3 | ||||
-rw-r--r-- | Documentation/RelNotes-1.5.2.2.txt | 61 | ||||
-rw-r--r-- | Documentation/asciidoc.conf | 3 | ||||
-rw-r--r-- | Documentation/git-blame.txt | 7 | ||||
-rw-r--r-- | Documentation/git-cvsexportcommit.txt | 2 | ||||
-rw-r--r-- | Documentation/git-cvsimport.txt | 23 | ||||
-rw-r--r-- | Documentation/user-manual.txt | 4 | ||||
-rw-r--r-- | Makefile | 21 | ||||
-rw-r--r-- | builtin-blame.c | 16 | ||||
-rw-r--r-- | builtin-revert.c | 4 | ||||
-rw-r--r-- | cache.h | 16 | ||||
-rw-r--r-- | commit.c | 2 | ||||
-rw-r--r-- | compat/hstrerror.c | 21 | ||||
-rw-r--r-- | config.c | 2 | ||||
-rwxr-xr-x | contrib/gitview/gitview | 21 | ||||
-rw-r--r-- | csum-file.c | 55 | ||||
-rw-r--r-- | csum-file.h | 2 | ||||
-rw-r--r-- | dir.c | 21 | ||||
-rwxr-xr-x | generate-cmdlist.sh | 2 | ||||
-rw-r--r-- | git-compat-util.h | 5 | ||||
-rwxr-xr-x | git-cvsimport.perl | 64 | ||||
-rwxr-xr-x | git-remote.perl | 1 | ||||
-rwxr-xr-x | git-svn.perl | 82 | ||||
-rwxr-xr-x | gitweb/gitweb.perl | 4 | ||||
-rw-r--r-- | merge-recursive.c | 2 | ||||
-rw-r--r-- | refs.c | 2 | ||||
-rw-r--r-- | remote.c | 7 | ||||
-rw-r--r-- | revision.c | 3 | ||||
-rw-r--r-- | sha1_file.c | 4 | ||||
-rwxr-xr-x | t/t9113-git-svn-dcommit-new-file.sh | 40 |
31 files changed, 322 insertions, 180 deletions
diff --git a/.gitignore b/.gitignore index bd49cd462..e8b060cbe 100644 --- a/.gitignore +++ b/.gitignore @@ -157,7 +157,7 @@ common-cmds.h *.tar.gz *.dsc *.deb -git-core.spec +git.spec *.exe *.[aos] *.py[co] diff --git a/Documentation/Makefile b/Documentation/Makefile index 2ad18e0ac..cc563247a 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -37,6 +37,9 @@ man7dir=$(mandir)/man7 ASCIIDOC=asciidoc ASCIIDOC_EXTRA = +ifdef ASCIIDOC8 +ASCIIDOC_EXTRA += -a asciidoc7compatible +endif INSTALL?=install DOC_REF = origin/man diff --git a/Documentation/RelNotes-1.5.2.2.txt b/Documentation/RelNotes-1.5.2.2.txt new file mode 100644 index 000000000..f6393f8a9 --- /dev/null +++ b/Documentation/RelNotes-1.5.2.2.txt @@ -0,0 +1,61 @@ +GIT v1.5.2.2 Release Notes +========================== + +Fixes since v1.5.2.1 +-------------------- + +* Usability fix + + - git-gui is shipped with its updated blame interface. It is + rumored that the older one was not just unusable but was + active health hazard, but this one is actually pretty. + Please see for yourself. + +* Bugfixes + + - "git checkout fubar" was utterly confused when there is a + branch fubar and a tag fubar at the same time. It correctly + checks out the branch fubar now. + + - "git clone /path/foo" to clone a local /path/foo.git + repository left an incorrect configuration. + + - "git send-email" correctly unquotes RFC 2047 quoted names in + the patch-email before using their values. + + - We did not accept number of seconds since epoch older than + year 2000 as a valid timestamp. We now interpret positive + integers more than 8 digits as such, which allows us to + express timestamps more recent than March 1973. + + - git-cvsimport did not work when you have GIT_DIR to point + your repository at a nonstandard location. + + - Some systems (notably, Solaris) lack hstrerror() to make + h_errno human readable; prepare a replacement + implementation. + + - .gitignore file listed git-core.spec but what we generate is + git.spec, and nobody noticed for a long time. + + - "git-merge-recursive" does not try to run file level merge + on binary files. + + - "git-branch --track" did not create tracking configuration + correctly when the branch name had slash in it. + + - The email address of the user specified with user.email + configuration was overriden by EMAIL environment variable. + + - The tree parser did not warn about tree entries with + nonsense file modes, and assumed they must be blobs. + + - "git log -z" without any other request to generate diff still + invoked the diff machinery, wasting cycles. + +* Documentation + + - Many updates to fix stale or missing documentation. + + - Although our documentation was primarily meant to be formatted + with AsciiDoc7, formatting with AsciiDoc8 is supported better. diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf index 99302c5be..6b6220dfd 100644 --- a/Documentation/asciidoc.conf +++ b/Documentation/asciidoc.conf @@ -8,7 +8,8 @@ # the command. [attributes] -caret=^ +plus=+ +caret=^ startsb=[ endsb=] tilde=~ diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt index 44678b0c3..66f120370 100644 --- a/Documentation/git-blame.txt +++ b/Documentation/git-blame.txt @@ -8,7 +8,7 @@ git-blame - Show what revision and author last modified each line of a file SYNOPSIS -------- [verse] -'git-blame' [-c] [-b] [--root] [-s] [-l] [-t] [-f] [-n] [-p] [--incremental] [-L n,m] +'git-blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [--incremental] [-L n,m] [-S <revs-file>] [-M] [-C] [-C] [--since=<date>] [<rev> | --contents <file>] [--] <file> @@ -63,6 +63,11 @@ include::blame-options.txt[] -s:: Suppress author name and timestamp from the output. +-w:: + Ignore whitespace when comparing parent's version and + child's to find where the lines came from. + + THE PORCELAIN FORMAT -------------------- diff --git a/Documentation/git-cvsexportcommit.txt b/Documentation/git-cvsexportcommit.txt index 827711c3c..6c423e3a2 100644 --- a/Documentation/git-cvsexportcommit.txt +++ b/Documentation/git-cvsexportcommit.txt @@ -76,7 +76,7 @@ $ git-cvsexportcommit -v <commit-sha1> $ cvs commit -F .mgs <files> ------------ -Merge pending patches into CVS automatically -- only if you really know what you are doing :: +Merge pending patches into CVS automatically -- only if you really know what you are doing:: + ------------ $ export GIT_DIR=~/project/.git diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt index 3985e0164..fdd7ec7ed 100644 --- a/Documentation/git-cvsimport.txt +++ b/Documentation/git-cvsimport.txt @@ -13,7 +13,7 @@ SYNOPSIS [-A <author-conv-file>] [-p <options-for-cvsps>] [-P <file>] [-C <git_repository>] [-z <fuzz>] [-i] [-k] [-u] [-s <subst>] [-a] [-m] [-M <regex>] [-S <regex>] [-L <commitlimit>] - [<CVS_module>] + [-r <remote>] [<CVS_module>] DESCRIPTION @@ -25,10 +25,12 @@ Splitting the CVS log into patch sets is done by 'cvsps'. At least version 2.1 is required. You should *never* do any work of your own on the branches that are -created by git-cvsimport. The initial import will create and populate a +created by git-cvsimport. By default initial import will create and populate a "master" branch from the CVS repository's main branch which you're free to work with; after that, you need to 'git merge' incremental imports, or -any CVS branches, yourself. +any CVS branches, yourself. It is advisable to specify a named remote via +-r to separate and protect the incoming branches. + OPTIONS ------- @@ -51,10 +53,19 @@ OPTIONS The git repository to import to. If the directory doesn't exist, it will be created. Default is the current directory. +-r <remote>:: + The git remote to import this CVS repository into. + Moves all CVS branches into remotes/<remote>/<branch> + akin to the git-clone --use-separate-remote option. + -o <branch-for-HEAD>:: - The 'HEAD' branch from CVS is imported to the 'origin' branch within - the git repository, as 'HEAD' already has a special meaning for git. - Use this option if you want to import into a different branch. + When no remote is specified (via -r) the 'HEAD' branch + from CVS is imported to the 'origin' branch within the git + repository, as 'HEAD' already has a special meaning for git. + When a remote is specified the 'HEAD' branch is named + remotes/<remote>/master mirroring git-clone behaviour. + Use this option if you want to import into a different + branch. + Use '-o master' for continuing an import that was initially done by the old cvs2git tool. diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 0bfa21b3d..ff7c71d4f 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -2757,8 +2757,8 @@ As a result, the general consistency of an object can always be tested independently of the contents or the type of the object: all objects can be validated by verifying that (a) their hashes match the content of the file and (b) the object successfully inflates to a stream of bytes that -forms a sequence of <ascii type without space> + <space> + <ascii decimal -size> + <byte\0> + <binary object data>. +forms a sequence of <ascii type without space> {plus} <space> {plus} <ascii decimal +size> {plus} <byte\0> {plus} <binary object data>. The structured objects can further have their structure and connectivity to other objects verified. This is generally done with @@ -107,6 +107,8 @@ all:: # Define USE_STDEV below if you want git to care about the underlying device # change being considered an inode change from the update-cache perspective. # +# Define ASCIIDOC8 if you want to format documentation with AsciiDoc 8 +# # Define NO_PERL_MAKEMAKER if you cannot use Makefiles generated by perl's # MakeMaker (e.g. using ActiveState under Cygwin). # @@ -410,6 +412,7 @@ ifeq ($(uname_S),SunOS) NEEDS_NSL = YesPlease SHELL_PATH = /bin/bash NO_STRCASESTR = YesPlease + NO_HSTRERROR = YesPlease ifeq ($(uname_R),5.8) NEEDS_LIBICONV = YesPlease NO_UNSETENV = YesPlease @@ -654,6 +657,10 @@ endif ifdef NO_PERL_MAKEMAKER export NO_PERL_MAKEMAKER endif +ifdef NO_HSTRERROR + COMPAT_CFLAGS += -DNO_HSTRERROR + COMPAT_OBJS += compat/hstrerror.o +endif ifeq ($(TCLTK_PATH),) NO_TCLTK=NoThanks @@ -684,6 +691,10 @@ ifndef V endif endif +ifdef ASCIIDOC8 + export ASCIIDOC8 +endif + # Shell quote (do not use $(call) to accommodate ancient setups); SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER)) @@ -735,9 +746,13 @@ gitk-wish: gitk GIT-GUI-VARS chmod +x $@+ && \ mv -f $@+ $@ -git$X: git.c common-cmds.h $(BUILTIN_OBJS) $(GITLIBS) GIT-CFLAGS +git.o: git.c common-cmds.h GIT-CFLAGS + $(QUIET_CC)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \ + $(ALL_CFLAGS) -c $(filter %.c,$^) + +git$X: git.o $(BUILTIN_OBJS) $(GITLIBS) $(QUIET_LINK)$(CC) -DGIT_VERSION='"$(GIT_VERSION)"' \ - $(ALL_CFLAGS) -o $@ $(filter %.c,$^) \ + $(ALL_CFLAGS) -o $@ $(filter %.c,$^) git.o \ $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS) help.o: common-cmds.h @@ -748,6 +763,8 @@ git-merge-subtree$X: git-merge-recursive$X $(BUILT_INS): git$X $(QUIET_BUILT_IN)rm -f $@ && ln git$X $@ +common-cmds.h: ./generate-cmdlist.sh + common-cmds.h: $(wildcard Documentation/git-*.txt) $(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@ diff --git a/builtin-blame.c b/builtin-blame.c index 35471fc26..f7e2c1388 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -20,7 +20,7 @@ #include "mailmap.h" static char blame_usage[] = -"git-blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-L n,m] [-S <revs-file>] [-M] [-C] [-C] [--contents <filename>] [--incremental] [commit] [--] file\n" +"git-blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-w] [-L n,m] [-S <revs-file>] [-M] [-C] [-C] [--contents <filename>] [--incremental] [commit] [--] file\n" " -c Use the same output mode as git-annotate (Default: off)\n" " -b Show blank SHA-1 for boundary commits (Default: off)\n" " -l Show long commit SHA1 (Default: off)\n" @@ -30,6 +30,7 @@ static char blame_usage[] = " -n, --show-number Show original linenumber (Default: off)\n" " -s Suppress author name and timestamp (Default: off)\n" " -p, --porcelain Show in a format designed for machine consumption\n" +" -w Ignore whitespace differences\n" " -L n,m Process only line range n,m, counting from 1\n" " -M, -C Find line movements within and across files\n" " --incremental Show blame entries as we find them, incrementally\n" @@ -45,6 +46,7 @@ static int show_root; static int blank_boundary; static int incremental; static int cmd_is_annotate; +static int xdl_opts = XDF_NEED_MINIMAL; static struct path_list mailmap; #ifndef DEBUG @@ -515,7 +517,7 @@ static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o, xdemitconf_t xecfg; xdemitcb_t ecb; - xpp.flags = XDF_NEED_MINIMAL; + xpp.flags = xdl_opts; xecfg.ctxlen = context; xecfg.flags = 0; ecb.outf = xdiff_outf; @@ -1744,11 +1746,11 @@ static int read_ancestry(const char *graft_file) */ static int lineno_width(int lines) { - int i, width; + int i, width; - for (width = 1, i = 10; i <= lines + 1; width++) - i *= 10; - return width; + for (width = 1, i = 10; i <= lines + 1; width++) + i *= 10; + return width; } /* @@ -2159,6 +2161,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix) output_option |= OUTPUT_LONG_OBJECT_NAME; else if (!strcmp("-s", arg)) output_option |= OUTPUT_NO_AUTHOR; + else if (!strcmp("-w", arg)) + xdl_opts |= XDF_IGNORE_WHITESPACE; else if (!strcmp("-S", arg) && ++i < argc) revs_file = argv[i]; else if (!prefixcmp(arg, "-M")) { diff --git a/builtin-revert.c b/builtin-revert.c index 8f02ed7bd..499bbe734 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -25,7 +25,7 @@ static const char *cherry_pick_usage = "git-cherry-pick [--edit] [-n] [-r] [-x] static int edit; static int replay; -enum { REVERT, CHERRY_PICK } action; +static enum { REVERT, CHERRY_PICK } action; static int no_commit; static struct commit *commit; static int needed_deref; @@ -129,7 +129,7 @@ static char *get_encoding(const char *message) return NULL; } -struct lock_file msg_file; +static struct lock_file msg_file; static int msg_fd; static void add_to_msg(const char *string) @@ -225,6 +225,21 @@ extern void verify_non_filename(const char *prefix, const char *name); #define alloc_nr(x) (((x)+16)*3/2) +/* + * Realloc the buffer pointed at by variable 'x' so that it can hold + * at least 'nr' entries; the number of entries currently allocated + * is 'alloc', using the standard growing factor alloc_nr() macro. + * + * DO NOT USE any expression with side-effect for 'x' or 'alloc'. + */ +#define ALLOC_GROW(x, nr, alloc) \ + do { \ + if ((nr) >= alloc) { \ + alloc = alloc_nr(alloc); \ + x = xrealloc((x), alloc * sizeof(*(x))); \ + } \ + } while(0) + /* Initialize and use the cache information */ extern int read_index(struct index_state *); extern int read_index_from(struct index_state *, const char *path); @@ -354,7 +369,6 @@ extern int move_temp_to_file(const char *tmpfile, const char *filename); extern int has_sha1_pack(const unsigned char *sha1, const char **ignore); extern int has_sha1_file(const unsigned char *sha1); -extern void *map_sha1_file(const unsigned char *sha1, unsigned long *); extern int has_pack_file(const unsigned char *sha1); extern int has_pack_index(const unsigned char *sha1); @@ -27,7 +27,7 @@ struct sort_node const char *commit_type = "commit"; -struct cmt_fmt_map { +static struct cmt_fmt_map { const char *n; size_t cmp_len; enum cmit_fmt v; diff --git a/compat/hstrerror.c b/compat/hstrerror.c new file mode 100644 index 000000000..069c555da --- /dev/null +++ b/compat/hstrerror.c @@ -0,0 +1,21 @@ +#include <string.h> +#include <stdio.h> +#include <netdb.h> + +const char *githstrerror(int err) +{ + static char buffer[48]; + switch (err) + { + case HOST_NOT_FOUND: + return "Authoritative answer: host not found"; + case NO_DATA: + return "Valid name, no data record of requested type"; + case NO_RECOVERY: + return "Non recoverable errors, FORMERR, REFUSED, NOTIMP"; + case TRY_AGAIN: + return "Non-authoritative \"host not found\", or SERVERFAIL"; + } + sprintf(buffer, "Name resolution error %d", err); + return buffer; +} @@ -523,7 +523,7 @@ static int store_aux(const char* key, const char* value) return 0; } -static int write_error() +static int write_error(void) { fprintf(stderr, "Failed to write new configuration file\n"); diff --git a/contrib/gitview/gitview b/contrib/gitview/gitview index 098cb0135..593176662 100755 --- a/contrib/gitview/gitview +++ b/contrib/gitview/gitview @@ -352,6 +352,7 @@ class AnnotateWindow(object): self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) self.window.set_border_width(0) self.window.set_title("Git repository browser annotation window") + self.prev_read = "" # Use two thirds of the screen by default screen = self.window.get_screen() @@ -401,7 +402,10 @@ class AnnotateWindow(object): def data_ready(self, source, condition): while (1): try : - buffer = source.read(8192) + # A simple readline doesn't work + # a readline bug ?? + buffer = source.read(100) + except: # resource temporary not available return True @@ -411,6 +415,19 @@ class AnnotateWindow(object): source.close() return False + if (self.prev_read != ""): + buffer = self.prev_read + buffer + self.prev_read = "" + + if (buffer[len(buffer) -1] != '\n'): + try: + newline_index = buffer.rindex("\n") + except ValueError: + newline_index = 0 + + self.prev_read = buffer[newline_index:(len(buffer))] + buffer = buffer[0:newline_index] + for buff in buffer.split("\n"): annotate_line = re.compile('^([0-9a-f]{40}) (.+) (.+) (.+)$') m = annotate_line.match(buff) @@ -516,7 +533,7 @@ class AnnotateWindow(object): self.add_file_data(filename, commit_sha1, line_num) - fp = os.popen("git blame --incremental -- " + filename + " " + commit_sha1) + fp = os.popen("git blame --incremental -C -C -- " + filename + " " + commit_sha1) flags = fcntl.fcntl(fp.fileno(), fcntl.F_GETFL) fcntl.fcntl(fp.fileno(), fcntl.F_SETFL, flags | os.O_NONBLOCK) self.io_watch_tag = gobject.io_add_watch(fp, gobject.IO_IN, self.data_ready) diff --git a/csum-file.c b/csum-file.c index 510934262..9ab997120 100644 --- a/csum-file.c +++ b/csum-file.c @@ -73,33 +73,6 @@ int sha1write(struct sha1file *f, void *buf, unsigned int count) return 0; } -struct sha1file *sha1create(const char *fmt, ...) -{ - struct sha1file *f; - unsigned len; - va_list arg; - int fd; - - f = xmalloc(sizeof(*f)); - - va_start(arg, fmt); - len = vsnprintf(f->name, sizeof(f->name), fmt, arg); - va_end(arg); - if (len >= PATH_MAX) - die("you wascally wabbit, you"); - f->namelen = len; - - fd = open(f->name, O_CREAT | O_EXCL | O_WRONLY, 0666); - if (fd < 0) - die("unable to open %s (%s)", f->name, strerror(errno)); - f->fd = fd; - f->error = 0; - f->offset = 0; - f->do_crc = 0; - SHA1_Init(&f->ctx); - return f; -} - struct sha1file *sha1fd(int fd, const char *name) { struct sha1file *f; @@ -121,34 +94,6 @@ struct sha1file *sha1fd(int fd, const char *name) return f; } -int sha1write_compressed(struct sha1file *f, void *in, unsigned int size, int level) -{ - z_stream stream; - unsigned long maxsize; - void *out; - - memset(&stream, 0, sizeof(stream)); - deflateInit(&stream, level); - maxsize = deflateBound(&stream, size); - out = xmalloc(maxsize); - - /* Compress it */ - stream.next_in = in; - stream.avail_in = size; - - stream.next_out = out; - stream.avail_out = maxsize; - - while (deflate(&stream, Z_FINISH) == Z_OK) - /* nothing */; - deflateEnd(&stream); - - size = stream.total_out; - sha1write(f, out, size); - free(out); - return size; -} - void crc32_begin(struct sha1file *f) { f->crc32 = crc32(0, Z_NULL, 0); diff --git a/csum-file.h b/csum-file.h index 4e8b83e09..c3c792f1b 100644 --- a/csum-file.h +++ b/csum-file.h @@ -13,10 +13,8 @@ struct sha1file { }; extern struct sha1file *sha1fd(int fd, const char *name); -extern struct sha1file *sha1create(const char *fmt, ...) __attribute__((format (printf, 1, 2))); extern int sha1close(struct sha1file *, unsigned char *, int); extern int sha1write(struct sha1file *, void *, unsigned int); -extern int sha1write_compressed(struct sha1file *, void *, unsigned int, int); extern void crc32_begin(struct sha1file *); extern uint32_t crc32_end(struct sha1file *); @@ -271,27 +271,26 @@ int excluded(struct dir_struct *dir, const char *pathname) return 0; } -struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len) -{ +static struct dir_entry *dir_entry_new(const char *pathname, int len) { struct dir_entry *ent; - if (cache_name_pos(pathname, len) >= 0) - return NULL; - - if (dir->nr == dir->alloc) { - int alloc = alloc_nr(dir->alloc); - dir->alloc = alloc; - dir->entries = xrealloc(dir->entries, alloc*sizeof(ent)); - } ent = xmalloc(sizeof(*ent) + len + 1); ent->ignored = ent->ignored_dir = 0; ent->len = len; memcpy(ent->name, pathname, len); ent->name[len] = 0; - dir->entries[dir->nr++] = ent; return ent; } +struct dir_entry *dir_add_name(struct dir_struct *dir, const char *pathname, int len) +{ + if (cache_name_pos(pathname, len) >= 0) + return NULL; + + ALLOC_GROW(dir->entries, dir->nr, dir->alloc); + return dir->entries[dir->nr++] = dir_entry_new(pathname, len); +} + enum exist_status { index_nonexistent = 0, index_directory, diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh index 975777f05..17df47b95 100755 --- a/generate-cmdlist.sh +++ b/generate-cmdlist.sh @@ -7,7 +7,7 @@ struct cmdname_help char help[80]; }; -struct cmdname_help common_cmds[] = {" +static struct cmdname_help common_cmds[] = {" sort <<\EOF | add diff --git a/git-compat-util.h b/git-compat-util.h index 6bd8987b2..b2ab3f825 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -167,6 +167,11 @@ extern size_t gitstrlcpy(char *, const char *, size_t); extern uintmax_t gitstrtoumax(const char *, char **, int); #endif +#ifdef NO_HSTRERROR +#define hstrerror githstrerror +extern const char *githstrerror(int herror); +#endif + extern void release_pack_memory(size_t, int); static inline char* xstrdup(const char *str) diff --git a/git-cvsimport.perl b/git-cvsimport.perl index 3225a2a25..433b7fd32 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -29,7 +29,7 @@ use IPC::Open2; $SIG{'PIPE'}="IGNORE"; $ENV{'TZ'}="UTC"; -our ($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P, $opt_s,$opt_m,$opt_M,$opt_A,$opt_S,$opt_L, $opt_a); +our ($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P, $opt_s,$opt_m,$opt_M,$opt_A,$opt_S,$opt_L, $opt_a, $opt_r); my (%conv_author_name, %conv_author_email); sub usage(;$) { @@ -40,7 +40,7 @@ Usage: ${\basename $0} # fetch/update GIT from CVS [-o branch-for-HEAD] [-h] [-v] [-d CVSROOT] [-A author-conv-file] [-p opts-for-cvsps] [-P file] [-C GIT_repository] [-z fuzz] [-i] [-k] [-u] [-s subst] [-a] [-m] [-M regex] [-S regex] [-L commitlimit] - [CVS_module] + [-r remote] [CVS_module] END exit(1); } @@ -114,7 +114,7 @@ sub read_repo_config { } } -my $opts = "haivmkuo:d:p:C:z:s:M:P:A:S:L:"; +my $opts = "haivmkuo:d:p:r:C:z:s:M:P:A:S:L:"; read_repo_config($opts); getopts($opts) or usage(); usage if $opt_h; @@ -134,13 +134,21 @@ if ($opt_d) { } else { usage("CVSROOT needs to be set"); } -$opt_o ||= "origin"; $opt_s ||= "-"; $opt_a ||= 0; my $git_tree = $opt_C; $git_tree ||= "."; +my $remote; +if (defined $opt_r) { + $remote = 'refs/remotes/' . $opt_r; + $opt_o ||= "master"; +} else { + $opt_o ||= "origin"; + $remote = 'refs/heads'; +} + my $cvs_tree; if ($#ARGV == 0) { $cvs_tree = $ARGV[0]; @@ -522,7 +530,7 @@ sub get_headref ($$) { my $name = shift; my $git_dir = shift; - my $f = "$git_dir/refs/heads/$name"; + my $f = "$git_dir/$remote/$name"; if (open(my $fh, $f)) { chomp(my $r = <$fh>); is_sha1($r) or die "Cannot get head id for $name ($r): $!"; @@ -573,12 +581,12 @@ unless (-d $git_dir) { # Get the last import timestamps my $fmt = '($ref, $author) = (%(refname), %(author));'; - open(H, "git-for-each-ref --perl --format='$fmt' refs/heads |") or + open(H, "git-for-each-ref --perl --format='$fmt' $remote |") or die "Cannot run git-for-each-ref: $!\n"; while (defined(my $entry = <H>)) { my ($ref, $author); eval($entry) || die "cannot eval refs list: $@"; - my ($head) = ($ref =~ m|^refs/heads/(.*)|); + my ($head) = ($ref =~ m|^$remote/(.*)|); $author =~ /^.*\s(\d+)\s[-+]\d{4}$/; $branch_date{$head} = $1; } @@ -701,9 +709,9 @@ sub commit { $index{$branch} = tmpnam(); $ENV{GIT_INDEX_FILE} = $index{$branch}; if ($ancestor) { - system("git-read-tree", $ancestor); + system("git-read-tree", "$remote/$ancestor"); } else { - system("git-read-tree", $branch); + system("git-read-tree", "$remote/$branch"); } die "read-tree failed: $?\n" if $?; } @@ -762,7 +770,7 @@ sub commit { waitpid($pid,0); die "Error running git-commit-tree: $?\n" if $?; - system("git-update-ref refs/heads/$branch $cid") == 0 + system("git-update-ref $remote/$branch $cid") == 0 or die "Cannot write branch $branch for update: $!\n"; if ($tag) { @@ -772,30 +780,8 @@ sub commit { $xtag =~ tr/_/\./ if ( $opt_u ); $xtag =~ s/[\/]/$opt_s/g; - my $pid = open2($in, $out, 'git-mktag'); - print $out "object $cid\n". - "type commit\n". - "tag $xtag\n". - "tagger $author_name <$author_email>\n" - or die "Cannot create tag object $xtag: $!\n"; - close($out) - or die "Cannot create tag object $xtag: $!\n"; - - my $tagobj = <$in>; - chomp $tagobj; - - if ( !close($in) or waitpid($pid, 0) != $pid or - $? != 0 or $tagobj !~ /^[0123456789abcdef]{40}$/ ) { - die "Cannot create tag object $xtag: $!\n"; - } - - - open(C,">$git_dir/refs/tags/$xtag") + system('git-tag', $xtag, $cid) == 0 or die "Cannot create tag $xtag: $!\n"; - print C "$tagobj\n" - or die "Cannot write tag $xtag: $!\n"; - close(C) - or die "Cannot write tag $xtag: $!\n"; print "Created tag '$xtag' on '$branch'\n" if $opt_v; } @@ -883,12 +869,12 @@ while (<CVS>) { print STDERR "Branch $branch erroneously stems from itself -- changed ancestor to $opt_o\n"; $ancestor = $opt_o; } - if (-f "$git_dir/refs/heads/$branch") { + if (-f "$git_dir/$remote/$branch") { print STDERR "Branch $branch already exists!\n"; $state=11; next; } - unless (open(H,"$git_dir/refs/heads/$ancestor")) { + unless (open(H,"$git_dir/$remote/$ancestor")) { print STDERR "Branch $ancestor does not exist!\n"; $ignorebranch{$branch} = 1; $state=11; @@ -896,7 +882,7 @@ while (<CVS>) { } chomp(my $id = <H>); close(H); - unless (open(H,"> $git_dir/refs/heads/$branch")) { + unless (open(H,"> $git_dir/$remote/$branch")) { print STDERR "Could not create branch $branch: $!\n"; $ignorebranch{$branch} = 1; $state=11; @@ -1010,14 +996,16 @@ if ($orig_branch) { die "Fast-forward update failed: $?\n" if $?; } else { - system(qw(git-merge cvsimport HEAD), "refs/heads/$opt_o"); + system(qw(git-merge cvsimport HEAD), "$remote/$opt_o"); die "Could not merge $opt_o into the current branch.\n" if $?; } } else { $orig_branch = "master"; print "DONE; creating $orig_branch branch\n" if $opt_v; - system("git-update-ref", "refs/heads/master", "refs/heads/$opt_o") + system("git-update-ref", "refs/heads/master", "$remote/$opt_o") unless -f "$git_dir/refs/heads/master"; + system("git-symbolic-ref", "$remote/HEAD", "$remote/$opt_o") + if ($opt_r && $opt_o ne 'HEAD'); system('git-update-ref', 'HEAD', "$orig_branch"); unless ($opt_i) { system('git checkout'); diff --git a/git-remote.perl b/git-remote.perl index 576379912..b59cafdf8 100755 --- a/git-remote.perl +++ b/git-remote.perl @@ -258,6 +258,7 @@ sub show_remote { if ($info->{'PUSH'}) { my @pushed = map { s|^refs/heads/||; + s|^\+refs/heads/|+|; s|:refs/heads/|:|; $_; } @{$info->{'PUSH'}}; diff --git a/git-svn.perl b/git-svn.perl index e35006142..50128d728 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -38,14 +38,16 @@ use IPC::Open3; use Git; BEGIN { - my $s; + # import functions from Git into our packages, en masse + no strict 'refs'; foreach (qw/command command_oneline command_noisy command_output_pipe command_input_pipe command_close_pipe/) { - $s .= "*SVN::Git::Editor::$_ = *SVN::Git::Fetcher::$_ = ". - "*Git::SVN::Migration::$_ = ". - "*Git::SVN::Log::$_ = *Git::SVN::$_ = *$_ = *Git::$_; "; + for my $package ( qw(SVN::Git::Editor SVN::Git::Fetcher + Git::SVN::Migration Git::SVN::Log Git::SVN), + __PACKAGE__) { + *{"${package}::$_"} = \&{"Git::$_"}; + } } - eval $s; } my ($SVN); @@ -846,26 +848,26 @@ BEGIN { # some options are read globally, but can be overridden locally # per [svn-remote "..."] section. Command-line options will *NOT* # override options set in an [svn-remote "..."] section - my $e; - foreach (qw/follow_parent no_metadata use_svm_props - use_svnsync_props/) { - my $key = $_; + no strict 'refs'; + for my $option (qw/follow_parent no_metadata use_svm_props + use_svnsync_props/) { + my $key = $option; $key =~ tr/_//d; - $e .= "sub $_ { - my (\$self) = \@_; - return \$self->{-$_} if exists \$self->{-$_}; - my \$k = \"svn-remote.\$self->{repo_id}\.$key\"; - eval { command_oneline(qw/config --get/, \$k) }; - if (\$@) { - \$self->{-$_} = \$Git::SVN::_$_; + my $prop = "-$option"; + *$option = sub { + my ($self) = @_; + return $self->{$prop} if exists $self->{$prop}; + my $k = "svn-remote.$self->{repo_id}.$key"; + eval { command_oneline(qw/config --get/, $k) }; + if ($@) { + $self->{$prop} = ${"Git::SVN::_$option"}; } else { - my \$v = command_oneline(qw/config --bool/,\$k); - \$self->{-$_} = \$v eq 'false' ? 0 : 1; + my $v = command_oneline(qw/config --bool/,$k); + $self->{$prop} = $v eq 'false' ? 0 : 1; } - return \$self->{-$_} }\n"; + return $self->{$prop}; + } } - $e .= "1;\n"; - eval $e or die $@; } my %LOCKFILES; @@ -1457,7 +1459,7 @@ sub tmp_config { my (@args) = @_; my $old_def_config = "$ENV{GIT_DIR}/svn/config"; my $config = "$ENV{GIT_DIR}/svn/.metadata"; - if (-e $old_def_config && ! -e $config) { + if (! -f $config && -f $old_def_config) { rename $old_def_config, $config or die "Failed rename $old_def_config => $config: $!\n"; } @@ -2899,17 +2901,17 @@ my ($can_do_switch, %ignored_err, $RA); BEGIN { # enforce temporary pool usage for some simple functions - my $e; - foreach (qw/rev_proplist get_latest_revnum get_uuid get_repos_root/) { - $e .= "sub $_ { - my \$self = shift; - my \$pool = SVN::Pool->new; - my \@ret = \$self->SUPER::$_(\@_,\$pool); - \$pool->clear; - wantarray ? \@ret : \$ret[0]; }\n"; + no strict 'refs'; + for my $f (qw/rev_proplist get_latest_revnum get_uuid get_repos_root/) { + my $SUPER = "SUPER::$f"; + *$f = sub { + my $self = shift; + my $pool = SVN::Pool->new; + my @ret = $self->$SUPER(@_,$pool); + $pool->clear; + wantarray ? @ret : $ret[0]; + }; } - - eval "$e; 1;" or die $@; } sub new { @@ -3072,11 +3074,8 @@ sub gs_do_switch { $editor->{git_commit_ok}; } -sub gs_fetch_loop_common { - my ($self, $base, $head, $gsv, $globs) = @_; - return if ($base > $head); - my $inc = $_log_window_size; - my ($min, $max) = ($base, $head < $base + $inc ? $head : $base + $inc); +sub longest_common_path { + my ($gsv, $globs) = @_; my %common; my $common_max = scalar @$gsv; @@ -3108,6 +3107,15 @@ sub gs_fetch_loop_common { last; } } + $longest_path; +} + +sub gs_fetch_loop_common { + my ($self, $base, $head, $gsv, $globs) = @_; + return if ($base > $head); + my $inc = $_log_window_size; + my ($min, $max) = ($base, $head < $base + $inc ? $head : $base + $inc); + my $longest_path = longest_common_path($gsv, $globs); while (1) { my %revs; my $err; diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index a6383dc85..dbfb0441a 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -4206,8 +4206,10 @@ sub git_snapshot { my $git = git_cmd_str(); my $name = $project; + $name =~ s,([^/])/*\.git$,$1,; + $name = basename($name); + my $filename = to_utf8($name); $name =~ s/\047/\047\\\047\047/g; - my $filename = to_utf8(basename($project)); my $cmd; if ($suffix eq 'zip') { $filename .= "-$hash.$suffix"; diff --git a/merge-recursive.c b/merge-recursive.c index 4a82b741a..c8539ec0b 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -127,7 +127,7 @@ static void output(int v, const char *fmt, ...) va_end(args); } -static void flush_output() +static void flush_output(void) { struct output_buffer *b, *n; for (b = output_list; b; b = n) { @@ -150,7 +150,7 @@ static struct ref_list *sort_ref_list(struct ref_list *list) * Future: need to be in "struct repository" * when doing a full libification. */ -struct cached_refs { +static struct cached_refs { char did_loose; char did_packed; struct ref_list *loose; @@ -536,13 +536,14 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail, } if (pat) { - dst_name = xmalloc(strlen(pat->dst) + + const char *dst_side = pat->dst ? pat->dst : pat->src; + dst_name = xmalloc(strlen(dst_side) + strlen(src->name) - strlen(pat->src) + 2); - strcpy(dst_name, pat->dst); + strcpy(dst_name, dst_side); strcat(dst_name, src->name + strlen(pat->src)); } else - dst_name = strdup(src->name); + dst_name = xstrdup(src->name); dst_peer = find_ref_by_name(dst, dst_name); if (dst_peer && dst_peer->peer_ref) /* We're already sending something to this ref. */ diff --git a/revision.c b/revision.c index b12c25e2b..1f4590b89 100644 --- a/revision.c +++ b/revision.c @@ -1180,7 +1180,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i); if (opts > 0) { - revs->diff = 1; + if (strcmp(argv[i], "-z")) + revs->diff = 1; i += opts - 1; continue; } diff --git a/sha1_file.c b/sha1_file.c index 2b860868f..7628ee97d 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -413,7 +413,7 @@ static size_t peak_pack_mapped; static size_t pack_mapped; struct packed_git *packed_git; -void pack_report() +void pack_report(void) { fprintf(stderr, "pack_report: getpagesize() = %10" SZ_FMT "\n" @@ -959,7 +959,7 @@ int check_sha1_signature(const unsigned char *sha1, void *map, unsigned long siz return hashcmp(sha1, real_sha1) ? -1 : 0; } -void *map_sha1_file(const unsigned char *sha1, unsigned long *size) +static void *map_sha1_file(const unsigned char *sha1, unsigned long *size) { struct stat st; void *map; diff --git a/t/t9113-git-svn-dcommit-new-file.sh b/t/t9113-git-svn-dcommit-new-file.sh new file mode 100755 index 000000000..9ef0db904 --- /dev/null +++ b/t/t9113-git-svn-dcommit-new-file.sh @@ -0,0 +1,40 @@ +#!/bin/sh +# +# Copyright (c) 2007 Eric Wong +# + +# Don't run this test by default unless the user really wants it +# I don't like the idea of taking a port and possibly leaving a +# daemon running on a users system if the test fails. +# Not all git users will need to interact with SVN. +test -z "$SVNSERVE_PORT" && exit 0 + +test_description='git-svn dcommit new files over svn:// test' + +. ./lib-git-svn.sh + +start_svnserve () { + svnserve --listen-port $SVNSERVE_PORT \ + --root $rawsvnrepo \ + --listen-once \ + --listen-host 127.0.0.1 & +} + +test_expect_success 'start tracking an empty repo' " + svn mkdir -m 'empty dir' $svnrepo/empty-dir && + echo anon-access = write >> $rawsvnrepo/conf/svnserve.conf && + start_svnserve && + git svn init svn://127.0.0.1:$SVNSERVE_PORT && + git svn fetch + " + +test_expect_success 'create files in new directory with dcommit' " + mkdir git-new-dir && + echo hello > git-new-dir/world && + git update-index --add git-new-dir/world && + git commit -m hello && + start_svnserve && + git svn dcommit + " + +test_done |