diff --git a/.mailmap b/.mailmap index f88ae77a1f..373476bdc0 100644 --- a/.mailmap +++ b/.mailmap @@ -5,22 +5,28 @@ # same person appearing not to be so. # +Alexander Gavrilov Aneesh Kumar K.V Brian M. Carlson Chris Shoemaker Dana L. How Dana L. How Daniel Barkalow +David D. Kilzer David Kågedal +David S. Miller +Dirk Süsserott Fredrik Kuivinen H. Peter Anvin H. Peter Anvin H. Peter Anvin Horst H. von Brand +İsmail Dönmez Jay Soffian Joachim Berdal Haga Jon Loeliger Jon Seymour +Jonathan Nieder Junio C Hamano Karl Hasselström Kent Engstrom @@ -30,9 +36,12 @@ Li Hong Lukas Sandström Martin Langhoff Michael Coleman +Michael W. Olson Michele Ballabio Nanako Shiraishi +Nanako Shiraishi Nguyễn Thái Ngọc Duy +Philippe Bruhat Ramsay Allan Jones René Scharfe Robert Fitzsimons diff --git a/Documentation/RelNotes-1.5.6.4.txt b/Documentation/RelNotes-1.5.6.4.txt index 130418864e..d8968f1ecb 100644 --- a/Documentation/RelNotes-1.5.6.4.txt +++ b/Documentation/RelNotes-1.5.6.4.txt @@ -28,16 +28,20 @@ Fixes since v1.5.6.3 be huge by saying "no common commits", but this was an unnecessary noise; it is already known by the user anyway. +* "git-http-fetch" would have segfaulted when pack idx file retrieved + from the other side was corrupt. + +* "git-index-pack" used too much memory when dealing with a deep delta chain. + * "git-mailinfo" (hence "git-am") did not correctly handle in-body [PATCH] line to override the commit title taken from the mail Subject header. * "git-rebase -i -p" lost parents that are not involved in the history being rewritten. -Contains other various documentation fixes. +* "git-rm" lost track of where the index file was when GIT_DIR was + specified as a relative path. --- -exec >/var/tmp/1 -echo O=$(git describe maint) -O=v1.5.6.3-21-gebcce31 -git shortlog --no-merges $O..maint +* "git-rev-list --quiet" was not quiet as advertised. + +Contains other various documentation fixes. diff --git a/Documentation/RelNotes-1.6.0.txt b/Documentation/RelNotes-1.6.0.txt index b29ba25229..7da62d08d6 100644 --- a/Documentation/RelNotes-1.6.0.txt +++ b/Documentation/RelNotes-1.6.0.txt @@ -21,7 +21,9 @@ main git.git codebase. By default, packfiles created with this version uses delta-base-offset encoding introduced in v1.4.4. Pack idx files are using version 2 that allows larger packs and added robustness thanks to its CRC checking, -introduced in v1.5.2. +introduced in v1.5.2 and v1.4.4.5. If you want to keep your repositories +backwards compatible past these versions, set repack.useDeltaBaseOffset +to false or pack.indexVersion to 1, respectively. GIT_CONFIG, which was only documented as affecting "git config", but actually affected all git commands, now only affects "git config". @@ -134,6 +136,9 @@ Updates since v1.5.6 * git-archive can be told to omit certain paths from its output using export-ignore attributes. +* git-archive uses the zlib default compression level when creating + zip archive. + * With -v option, git-branch describes the remote tracking statistics similar to the way git-checkout reports by how many commits your branch is ahead/behind. @@ -153,6 +158,8 @@ Updates since v1.5.6 * git-clone can clone from a remote whose URL would be rewritten by configuration stored in $HOME/.gitconfig now. +* git-cvsserver learned to respond to "cvs co -c". + * git-diff --check now checks leftover merge conflict markers. * When remote side used to have branch 'foo' and git-fetch finds that now @@ -164,6 +171,8 @@ Updates since v1.5.6 * fast-export learned to export and import marks file; this can be used to interface with fast-import incrementally. +* fast-import and fast-export learned to export and import gitlinks. + * git-rebase records the original tip of branch in ORIG_HEAD before it is rewound. @@ -208,6 +217,6 @@ this release, unless otherwise noted. --- exec >/var/tmp/1 -O=v1.5.6.3-436-g1f8dc67 +O=v1.5.6.4-432-g6796399 echo O=$(git describe refs/heads/master) git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt index 2d01d0d100..c2f483a8d2 100644 --- a/Documentation/git-fast-import.txt +++ b/Documentation/git-fast-import.txt @@ -481,6 +481,9 @@ in octal. Git only supports the following modes: what you want. * `100755` or `755`: A normal, but executable, file. * `120000`: A symlink, the content of the file will be the link target. +* `160000`: A gitlink, SHA-1 of the object refers to a commit in + another repository. Git links can only be specified by SHA or through + a commit mark. They are used to implement submodules. In both formats `` is the complete path of the file to be added (if not already existing) or modified (if already existing). diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt index 019e4ca8f5..a7487d3dfd 100644 --- a/Documentation/git-merge.txt +++ b/Documentation/git-merge.txt @@ -57,50 +57,31 @@ HOW MERGE WORKS A merge is always between the current `HEAD` and one or more commits (usually, branch head or tag), and the index file must -exactly match the -tree of `HEAD` commit (i.e. the contents of the last commit) when -it happens. In other words, `git diff --cached HEAD` must -report no changes. +match the tree of `HEAD` commit (i.e. the contents of the last commit) +when it starts out. In other words, `git diff --cached HEAD` must +report no changes. (One exception is when the changed index +entries are already in the same state that would result from +the merge anyway.) -[NOTE] -This is a bit of a lie. In certain special cases, your index is -allowed to be different from the tree of the `HEAD` commit. The most -notable case is when your `HEAD` commit is already ahead of what -is being merged, in which case your index can have arbitrary -differences from your `HEAD` commit. Also, your index entries -may have differences from your `HEAD` commit that match -the result of a trivial merge (e.g. you received the same patch -from an external source to produce the same result as what you are -merging). For example, if a path did not exist in the common -ancestor and your head commit but exists in the tree you are -merging into your repository, and if you already happen to have -that path exactly in your index, the merge does not have to -fail. +Three kinds of merge can happen: -Otherwise, merge will refuse to do any harm to your repository -(that is, it may fetch the objects from remote, and it may even -update the local branch used to keep track of the remote branch -with `git pull remote rbranch:lbranch`, but your working tree, -`.git/HEAD` pointer and index file are left intact). In addition, -merge always sets `.git/ORIG_HEAD` to the original state of HEAD so -a problematic merge can be removed by using `git reset ORIG_HEAD`. +* The merged commit is already contained in `HEAD`. This is the + simplest case, called "Already up-to-date." -You may have local modifications in the working tree files. In -other words, 'git-diff' is allowed to report changes. -However, the merge uses your working tree as the working area, -and in order to prevent the merge operation from losing such -changes, it makes sure that they do not interfere with the -merge. Those complex tables in read-tree documentation define -what it means for a path to "interfere with the merge". And if -your local modifications interfere with the merge, again, it -stops before touching anything. +* `HEAD` is already contained in the merged commit. This is the + most common case especially when involved through 'git pull': + you are tracking an upstream repository, committed no local + changes and now you want to update to a newer upstream revision. + Your `HEAD` (and the index) is updated to at point the merged + commit, without creating an extra merge commit. This is + called "Fast-forward". -So in the above two "failed merge" case, you do not have to -worry about loss of data --- you simply were not ready to do -a merge, so no merge happened at all. You may want to finish -whatever you were in the middle of doing, and retry the same -pull after you are done and ready. +* Both the merged commit and `HEAD` are independent and must be + tied together by a merge commit that has them both as its parents. + The rest of this section describes this "True merge" case. +The chosen merge strategy merges the two commits into a single +new source tree. When things cleanly merge, these things happen: 1. The results are updated both in the index file and in your @@ -142,12 +123,13 @@ After seeing a conflict, you can do two things: * Decide not to merge. The only clean-up you need are to reset the index file to the `HEAD` commit to reverse 2. and to clean - up working tree changes made by 2. and 3.; 'git-reset' can + up working tree changes made by 2. and 3.; 'git-reset --hard' can be used for this. * Resolve the conflicts. `git diff` would report only the - conflicting paths because of the above 2. and 3. Edit the - working tree files into a desirable shape, 'git-add' or 'git-rm' + conflicting paths because of the above 2. and 3. + Edit the working tree files into a desirable shape + ('git mergetool' can ease this task), 'git-add' or 'git-rm' them, to make the index file contain what the merge result should be, and run 'git-commit' to commit the result. diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt index bb4e6fbf59..829b03201d 100644 --- a/Documentation/git-submodule.txt +++ b/Documentation/git-submodule.txt @@ -18,24 +18,44 @@ SYNOPSIS DESCRIPTION ----------- -Submodules are a special kind of tree entries which refer to a particular tree -state in another repository. The tree entry describes -the existence of a submodule with the given name and the exact revision that -should be used, while an entry in `.gitmodules` file gives the location of -the repository. +Submodules allow foreign repositories to be embedded within +a dedicated subdirectory of the source tree, always pointed +at a particular commit. -When checked out, submodules will maintain their own independent repositories -within their directories; the only link between the submodule and the "parent -project" is the tree entry within the parent project mentioned above. +They are not to be confused with remotes, which are meant mainly +for branches of the same project; submodules are meant for +different projects you would like to make part of your source tree, +while the history of the two projects still stays completely +independent and you cannot modify the contents of the submodule +from within the main project. +If you want to merge the project histories and want to treat the +aggregated whole as a single project from then on, you may want to +add a remote for the other project and use the 'subtree' merge strategy, +instead of treating the other project as a submodule. Directories +that come from both projects can be cloned and checked out as a whole +if you choose to go that route. -This command will manage the tree entries and contents of the gitmodules file -for you, as well as inspecting the status of your submodules and updating them. -When adding a new submodule to the tree, the 'add' subcommand is to be used. -However, when pulling a tree containing submodules, these will not be checked -out by default; the 'init' and 'update' subcommands will maintain submodules -checked out and at appropriate revision in your working tree. You can inspect -the current status of your submodules using the 'submodule' subcommand and get -an overview of changes 'update' would perform using the 'summary' subcommand. +Submodules are composed from a so-called `gitlink` tree entry +in the main repository that refers to a particular commit object +within the inner repository that is completely separate. +A record in the `.gitmodules` file at the root of the source +tree assigns a logical name to the submodule and describes +the default URL the submodule shall be cloned from. +The logical name can be used for overriding this URL within your +local repository configuration (see 'submodule init'). + +This command will manage the tree entries and contents of the +gitmodules file for you, as well as inspect the status of your +submodules and update them. +When adding a new submodule to the tree, the 'add' subcommand +is to be used. However, when pulling a tree containing submodules, +these will not be checked out by default; +the 'init' and 'update' subcommands will maintain submodules +checked out and at appropriate revision in your working tree. +You can briefly inspect the up-to-date status of your submodules +using the 'status' subcommand and get a detailed overview of the +difference between the index and checkouts using the 'summary' +subcommand. COMMANDS @@ -78,10 +98,15 @@ status:: repository. This command is the default command for 'git-submodule'. init:: - Initialize the submodules, i.e. register in .git/config each submodule - name and url found in .gitmodules. The key used in .git/config is - `submodule.$name.url`. This command does not alter existing information - in .git/config. + Initialize the submodules, i.e. register each submodule name + and url found in .gitmodules into .git/config. + The key used in .git/config is `submodule.$name.url`. + This command does not alter existing information in .git/config. + You can then customize the submodule clone URLs in .git/config + for your local setup and proceed to 'git submodule update'; + you can also just use 'git submodule update --init' without + the explicit 'init' step if you do not intend to customize + any submodule locations. update:: Update the registered submodules, i.e. clone missing submodules and diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt index a91fd214d2..6b930bc163 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.txt @@ -88,6 +88,16 @@ OPTIONS sometimes helpful when working with a big project on a filesystem that has very slow lstat(2) system call (e.g. cifs). ++ +This option can be also used as a coarse file-level mechanism +to ignore uncommitted changes in tracked files (akin to what +`.gitignore` does for untracked files). +You should remember that an explicit 'git add' operation will +still cause the file to be refreshed from the working tree. +Git will fail (gracefully) in case it needs to modify this file +in the index e.g. when merging in a commit; +thus, in case the assumed-untracked file is changed upstream, +you will need to handle the situation manually. -g:: --again:: diff --git a/Documentation/git.txt b/Documentation/git.txt index 27b9d31f7e..44ea35e949 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,12 +43,13 @@ unreleased) version of git, that is available from 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v1.5.6.3/git.html[documentation for release 1.5.6.3] +* link:v1.5.6.4/git.html[documentation for release 1.5.6.4] * release notes for - link:RelNotes-1.5.6.3.txt[1.5.6.3]. - link:RelNotes-1.5.6.2.txt[1.5.6.2]. - link:RelNotes-1.5.6.1.txt[1.5.6.1]. + link:RelNotes-1.5.6.4.txt[1.5.6.4], + link:RelNotes-1.5.6.3.txt[1.5.6.3], + link:RelNotes-1.5.6.2.txt[1.5.6.2], + link:RelNotes-1.5.6.1.txt[1.5.6.1], link:RelNotes-1.5.6.txt[1.5.6]. * link:v1.5.5.4/git.html[documentation for release 1.5.5.4] diff --git a/Documentation/gitignore.txt b/Documentation/gitignore.txt index fc0efd8ec8..59321a2e82 100644 --- a/Documentation/gitignore.txt +++ b/Documentation/gitignore.txt @@ -13,9 +13,14 @@ DESCRIPTION ----------- A `gitignore` file specifies intentionally untracked files that -git should ignore. Each line in a `gitignore` file specifies a -pattern. +git should ignore. +Note that all the `gitignore` files really concern only files +that are not already tracked by git; +in order to ignore uncommitted changes in already tracked files, +please refer to the 'git update-index --assume-unchanged' +documentation. +Each line in a `gitignore` file specifies a pattern. When deciding whether to ignore a path, git normally checks `gitignore` patterns from multiple sources, with the following order of precedence, from highest to lowest (within one level of diff --git a/Documentation/technical/api-run-command.txt b/Documentation/technical/api-run-command.txt index 3e1342acf4..75aa5d4923 100644 --- a/Documentation/technical/api-run-command.txt +++ b/Documentation/technical/api-run-command.txt @@ -30,7 +30,7 @@ Functions start_command() followed by finish_command(). Takes a pointer to a `struct child_process` that specifies the details. -`run_command_v_opt`, `run_command_v_opt_dir`, `run_command_v_opt_cd_env`:: +`run_command_v_opt`, `run_command_v_opt_cd`, `run_command_v_opt_cd_env`:: Convenience functions that encapsulate a sequence of start_command() followed by finish_command(). The argument argv diff --git a/Makefile b/Makefile index 3e695c1949..61f9ea1634 100644 --- a/Makefile +++ b/Makefile @@ -1204,6 +1204,9 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) +git-shell$X: compat/strlcpy.o abspath.o ctype.o exec_cmd.o quote.o strbuf.o usage.o wrapper.o shell.o + $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) + $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h) builtin-revert.o wt-status.o: wt-status.h diff --git a/archive-tar.c b/archive-tar.c index f9eb726116..13029619e5 100644 --- a/archive-tar.c +++ b/archive-tar.c @@ -2,9 +2,7 @@ * Copyright (c) 2005, 2006 Rene Scharfe */ #include "cache.h" -#include "commit.h" #include "tar.h" -#include "builtin.h" #include "archive.h" #define RECORDSIZE (512) diff --git a/archive-zip.c b/archive-zip.c index d56e5cfc1e..cf285044e3 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -2,11 +2,6 @@ * Copyright (c) 2006 Rene Scharfe */ #include "cache.h" -#include "commit.h" -#include "blob.h" -#include "tree.h" -#include "quote.h" -#include "builtin.h" #include "archive.h" static int zip_date; @@ -93,7 +88,7 @@ static void copy_le32(unsigned char *dest, unsigned int n) } static void *zlib_deflate(void *data, unsigned long size, - unsigned long *compressed_size) + int compression_level, unsigned long *compressed_size) { z_stream stream; unsigned long maxsize; @@ -101,7 +96,7 @@ static void *zlib_deflate(void *data, unsigned long size, int result; memset(&stream, 0, sizeof(stream)); - deflateInit(&stream, zlib_compression_level); + deflateInit(&stream, compression_level); maxsize = deflateBound(&stream, size); buffer = xmalloc(maxsize); @@ -157,7 +152,7 @@ static int write_zip_entry(struct archiver_args *args, method = 0; attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) : (mode & 0111) ? ((mode) << 16) : 0; - if (S_ISREG(mode) && zlib_compression_level != 0) + if (S_ISREG(mode) && args->compression_level != 0) method = 8; crc = crc32(crc, buffer, size); out = buffer; @@ -169,7 +164,8 @@ static int write_zip_entry(struct archiver_args *args, } if (method == 8) { - deflated = zlib_deflate(buffer, size, &compressed_size); + deflated = zlib_deflate(buffer, size, args->compression_level, + &compressed_size); if (deflated && compressed_size - 6 < size) { /* ZLIB --> raw compressed data (see RFC 1950) */ /* CMF and FLG ... */ diff --git a/archive.h b/archive.h index 96bb1cd853..4a02371f37 100644 --- a/archive.h +++ b/archive.h @@ -13,6 +13,7 @@ struct archiver_args { time_t time; const char **pathspec; unsigned int verbose : 1; + int compression_level; }; typedef int (*write_archive_fn_t)(struct archiver_args *); diff --git a/builtin-archive.c b/builtin-archive.c index d5e3af879e..df97724696 100644 --- a/builtin-archive.c +++ b/builtin-archive.c @@ -7,10 +7,8 @@ #include "archive.h" #include "commit.h" #include "tree-walk.h" -#include "exec_cmd.h" #include "pkt-line.h" #include "sideband.h" -#include "attr.h" static const char archive_usage[] = \ "git archive --format= [--prefix=/] [--verbose] [] [path...]"; @@ -185,9 +183,10 @@ int parse_archive_args(int argc, const char **argv, const struct archiver **ar, if (!*ar) die("Unknown archive format '%s'", format); + args->compression_level = Z_DEFAULT_COMPRESSION; if (compression_level != -1) { if ((*ar)->flags & USES_ZLIB_COMPRESSION) - zlib_compression_level = compression_level; + args->compression_level = compression_level; else { die("Argument not supported for format '%s': -%d", format, compression_level); diff --git a/builtin-clone.c b/builtin-clone.c index 244abe2356..352224591f 100644 --- a/builtin-clone.c +++ b/builtin-clone.c @@ -95,35 +95,38 @@ static char *get_repo_path(const char *repo, int *is_bundle) static char *guess_dir_name(const char *repo, int is_bundle) { - const char *p, *start, *end, *limit; - int after_slash_or_colon; + const char *end = repo + strlen(repo), *start; - /* Guess dir name from repository: strip trailing '/', - * strip trailing '[:/]*.{git,bundle}', strip leading '.*[/:]'. */ + /* + * Strip trailing slashes and /.git + */ + while (repo < end && is_dir_sep(end[-1])) + end--; + if (end - repo > 5 && is_dir_sep(end[-5]) && + !strncmp(end - 4, ".git", 4)) { + end -= 5; + while (repo < end && is_dir_sep(end[-1])) + end--; + } - after_slash_or_colon = 1; - limit = repo + strlen(repo); - start = repo; - end = limit; - for (p = repo; p < limit; p++) { - const char *prefix = is_bundle ? ".bundle" : ".git"; - if (!prefixcmp(p, prefix)) { - if (!after_slash_or_colon) - end = p; - p += strlen(prefix) - 1; - } else if (!prefixcmp(p, ".bundle")) { - if (!after_slash_or_colon) - end = p; - p += 7; - } else if (is_dir_sep(*p) || *p == ':') { - if (end == limit) - end = p; - after_slash_or_colon = 1; - } else if (after_slash_or_colon) { - start = p; - end = limit; - after_slash_or_colon = 0; - } + /* + * Find last component, but be prepared that repo could have + * the form "remote.example.com:foo.git", i.e. no slash + * in the directory part. + */ + start = end; + while (repo < start && !is_dir_sep(start[-1]) && start[-1] != ':') + start--; + + /* + * Strip .{bundle,git}. + */ + if (is_bundle) { + if (end - start > 7 && !strncmp(end - 7, ".bundle", 7)) + end -= 7; + } else { + if (end - start > 4 && !strncmp(end - 4, ".git", 4)) + end -= 4; } return xstrndup(start, end - start); diff --git a/builtin-fast-export.c b/builtin-fast-export.c index 76f3167276..a443d59460 100644 --- a/builtin-fast-export.c +++ b/builtin-fast-export.c @@ -136,9 +136,18 @@ static void show_filemodify(struct diff_queue_struct *q, if (is_null_sha1(spec->sha1)) printf("D %s\n", spec->path); else { - struct object *object = lookup_object(spec->sha1); - printf("M %06o :%d %s\n", spec->mode, - get_object_mark(object), spec->path); + /* + * Links refer to objects in another repositories; + * output the SHA-1 verbatim. + */ + if (S_ISGITLINK(spec->mode)) + printf("M %06o %s %s\n", spec->mode, + sha1_to_hex(spec->sha1), spec->path); + else { + struct object *object = lookup_object(spec->sha1); + printf("M %06o :%d %s\n", spec->mode, + get_object_mark(object), spec->path); + } } } } @@ -196,8 +205,10 @@ static void handle_commit(struct commit *commit, struct rev_info *rev) diff_root_tree_sha1(commit->tree->object.sha1, "", &rev->diffopt); + /* Export the referenced blobs, and remember the marks. */ for (i = 0; i < diff_queued_diff.nr; i++) - handle_object(diff_queued_diff.queue[i]->two->sha1); + if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode)) + handle_object(diff_queued_diff.queue[i]->two->sha1); mark_next_object(&commit->object); if (!is_encoding_utf8(encoding)) diff --git a/builtin-remote.c b/builtin-remote.c index 1491354a9d..db12668cfe 100644 --- a/builtin-remote.c +++ b/builtin-remote.c @@ -147,6 +147,15 @@ struct branch_info { static struct path_list branch_list; +static const char *abbrev_ref(const char *name, const char *prefix) +{ + const char *abbrev = skip_prefix(name, prefix); + if (abbrev) + return abbrev; + return name; +} +#define abbrev_branch(name) abbrev_ref((name), "refs/heads/") + static int config_read_branches(const char *key, const char *value, void *cb) { if (!prefixcmp(key, "branch.")) { @@ -176,18 +185,12 @@ static int config_read_branches(const char *key, const char *value, void *cb) info->remote = xstrdup(value); } else { char *space = strchr(value, ' '); - const char *ptr = skip_prefix(value, "refs/heads/"); - if (ptr) - value = ptr; + value = abbrev_branch(value); while (space) { char *merge; merge = xstrndup(value, space - value); path_list_append(merge, &info->merge); - ptr = skip_prefix(space + 1, "refs/heads/"); - if (ptr) - value = ptr; - else - value = space + 1; + value = abbrev_branch(space + 1); space = strchr(value, ' '); } path_list_append(xstrdup(value), &info->merge); @@ -219,12 +222,7 @@ static int handle_one_branch(const char *refname, refspec.dst = (char *)refname; if (!remote_find_tracking(states->remote, &refspec)) { struct path_list_item *item; - const char *name, *ptr; - ptr = skip_prefix(refspec.src, "refs/heads/"); - if (ptr) - name = ptr; - else - name = refspec.src; + const char *name = abbrev_branch(refspec.src); /* symbolic refs pointing nowhere were handled already */ if ((flags & REF_ISSYMREF) || unsorted_path_list_has_path(&states->tracked, @@ -253,7 +251,6 @@ static int get_ref_states(const struct ref *ref, struct ref_states *states) struct path_list *target = &states->tracked; unsigned char sha1[20]; void *util = NULL; - const char *ptr; if (!ref->peer_ref || read_ref(ref->peer_ref->name, sha1)) target = &states->new; @@ -262,10 +259,7 @@ static int get_ref_states(const struct ref *ref, struct ref_states *states) if (hashcmp(sha1, ref->new_sha1)) util = &states; } - ptr = skip_prefix(ref->name, "refs/heads/"); - if (!ptr) - ptr = ref->name; - path_list_append(ptr, target)->util = util; + path_list_append(abbrev_branch(ref->name), target)->util = util; } free_refs(fetch_map); @@ -460,10 +454,8 @@ static int append_ref_to_tracked_list(const char *refname, memset(&refspec, 0, sizeof(refspec)); refspec.dst = (char *)refname; - if (!remote_find_tracking(states->remote, &refspec)) { - path_list_append(skip_prefix(refspec.src, "refs/heads/"), - &states->tracked); - } + if (!remote_find_tracking(states->remote, &refspec)) + path_list_append(abbrev_branch(refspec.src), &states->tracked); return 0; } @@ -530,15 +522,10 @@ static int show(int argc, const char **argv) "es" : ""); for (i = 0; i < states.remote->push_refspec_nr; i++) { struct refspec *spec = states.remote->push + i; - const char *p = "", *q = ""; - if (spec->src) - p = skip_prefix(spec->src, "refs/heads/"); - if (spec->dst) - q = skip_prefix(spec->dst, "refs/heads/"); printf(" %s%s%s%s", spec->force ? "+" : "", - p ? p : spec->src, - spec->dst ? ":" : "", - q ? q : spec->dst); + abbrev_branch(spec->src), + spec->dst ? ":" : "", + spec->dst ? abbrev_branch(spec->dst) : ""); } printf("\n"); } @@ -588,7 +575,7 @@ static int prune(int argc, const char **argv) result |= delete_ref(refname, NULL); printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned", - skip_prefix(refname, "refs/remotes/")); + abbrev_ref(refname, "refs/remotes/")); } /* NEEDSWORK: free remote */ diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 8e1720c45b..893762c80f 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -590,6 +590,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) revs.commit_format = CMIT_FMT_UNSPECIFIED; argc = setup_revisions(argc, argv, &revs, NULL); + quiet = DIFF_OPT_TST(&revs.diffopt, QUIET); for (i = 1 ; i < argc; i++) { const char *arg = argv[i]; @@ -621,10 +622,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) read_revisions_from_stdin(&revs); continue; } - if (!strcmp(arg, "--quiet")) { - quiet = 1; - continue; - } usage(rev_list_usage); } diff --git a/builtin-rm.c b/builtin-rm.c index 56454ec8f4..ee8247b08c 100644 --- a/builtin-rm.c +++ b/builtin-rm.c @@ -146,11 +146,6 @@ int cmd_rm(int argc, const char **argv, const char *prefix) git_config(git_default_config, NULL); - newfd = hold_locked_index(&lock_file, 1); - - if (read_cache() < 0) - die("index file corrupt"); - argc = parse_options(argc, argv, builtin_rm_options, builtin_rm_usage, 0); if (!argc) usage_with_options(builtin_rm_usage, builtin_rm_options); @@ -158,6 +153,11 @@ int cmd_rm(int argc, const char **argv, const char *prefix) if (!index_only) setup_work_tree(); + newfd = hold_locked_index(&lock_file, 1); + + if (read_cache() < 0) + die("index file corrupt"); + pathspec = get_pathspec(prefix, argv); seen = NULL; for (i = 0; pathspec[i] ; i++) diff --git a/fast-import.c b/fast-import.c index c4d054ecc7..7089e6f9e6 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1868,6 +1868,7 @@ static void file_change_m(struct branch *b) case S_IFREG | 0644: case S_IFREG | 0755: case S_IFLNK: + case S_IFGITLINK: case 0644: case 0755: /* ok */ @@ -1900,7 +1901,20 @@ static void file_change_m(struct branch *b) p = uq.buf; } - if (inline_data) { + if (S_ISGITLINK(mode)) { + if (inline_data) + die("Git links cannot be specified 'inline': %s", + command_buf.buf); + else if (oe) { + if (oe->type != OBJ_COMMIT) + die("Not a commit (actually a %s): %s", + typename(oe->type), command_buf.buf); + } + /* + * Accept the sha1 without checking; it expected to be in + * another repository. + */ + } else if (inline_data) { static struct strbuf buf = STRBUF_INIT; if (p != uq.buf) { diff --git a/git-cvsserver.perl b/git-cvsserver.perl index e5ba57f394..b0a805c688 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -801,6 +801,18 @@ sub req_co argsplit("co"); + # Provide list of modules, if -c was used. + if (exists $state->{opt}{c}) { + my $showref = `git show-ref --heads`; + for my $line (split '\n', $showref) { + if ( $line =~ m% refs/heads/(.*)$% ) { + print "M $1\t$1\n"; + } + } + print "ok\n"; + return 1; + } + my $module = $state->{args}[0]; $state->{module} = $module; my $checkout_path = $module; @@ -947,21 +959,15 @@ sub req_update # projects (heads in this case) to checkout. # if ($state->{module} eq '') { - my $heads_dir = $state->{CVSROOT} . '/refs/heads'; - if (!opendir HEADS, $heads_dir) { - print "E [server aborted]: Failed to open directory, " - . "$heads_dir: $!\nerror\n"; - return 0; - } + my $showref = `git show-ref --heads`; print "E cvs update: Updating .\n"; - while (my $head = readdir(HEADS)) { - if (-f $state->{CVSROOT} . '/refs/heads/' . $head) { - print "E cvs update: New directory `$head'\n"; - } - } - closedir HEADS; - print "ok\n"; - return 1; + for my $line (split '\n', $showref) { + if ( $line =~ m% refs/heads/(.*)$% ) { + print "E cvs update: New directory `$1'\n"; + } + } + print "ok\n"; + return 1; } diff --git a/http-walker.c b/http-walker.c index 51c18f2685..9dc6b27b45 100644 --- a/http-walker.c +++ b/http-walker.c @@ -442,6 +442,8 @@ static int setup_index(struct walker *walker, struct alt_base *repo, unsigned ch return -1; new_pack = parse_pack_index(sha1); + if (!new_pack) + return -1; /* parse_pack_index() already issued error message */ new_pack->next = repo->packs; repo->packs = new_pack; return 0; diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh index 316775ecd9..79c06adf1f 100755 --- a/t/t3600-rm.sh +++ b/t/t3600-rm.sh @@ -217,4 +217,16 @@ test_expect_success 'Remove nonexistent file returns nonzero exit status' ' test_must_fail git rm nonexistent ' +test_expect_success 'Call "rm" from outside the work tree' ' + mkdir repo && + cd repo && + git init && + echo something > somefile && + git add somefile && + git commit -m "add a file" && + (cd .. && + git --git-dir=repo/.git --work-tree=repo rm somefile) && + test_must_fail git ls-files --error-unmatch somefile +' + test_done diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index de5b9802c9..1c857cf4ab 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -13,7 +13,7 @@ test_expect_success \ test_expect_success \ 'Setup helper tool' \ - '(echo "#!/bin/sh" + '(echo "#!$SHELL_PATH" echo shift echo output=1 echo "while test -f commandline\$output; do output=\$((\$output+1)); done" @@ -138,7 +138,7 @@ test_expect_success 'Valid In-Reply-To when prompting' ' ' test_expect_success 'setup fake editor' ' - (echo "#!/bin/sh" && + (echo "#!$SHELL_PATH" && echo "echo fake edit >>\"\$1\"" ) >fake-editor && chmod +x fake-editor @@ -235,7 +235,7 @@ test_expect_success 'sendemail.cc unset' ' test_expect_success '--compose adds MIME for utf8 body' ' clean_fake_sendmail && - (echo "#!/bin/sh" && + (echo "#!$SHELL_PATH" && echo "echo utf8 body: àéìöú >>\"\$1\"" ) >fake-editor-utf8 && chmod +x fake-editor-utf8 && @@ -254,7 +254,7 @@ test_expect_success '--compose adds MIME for utf8 body' ' test_expect_success '--compose respects user mime type' ' clean_fake_sendmail && - (echo "#!/bin/sh" && + (echo "#!$SHELL_PATH" && echo "(echo MIME-Version: 1.0" echo " echo Content-Type: text/plain\\; charset=iso-8859-1" echo " echo Content-Transfer-Encoding: 8bit" diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh index e17afa8c30..1fc06c5a23 100755 --- a/t/t9300-fast-import.sh +++ b/t/t9300-fast-import.sh @@ -918,4 +918,156 @@ test_expect_success \ grep "progress " expect && test_cmp expect actual' +### +### series P (gitlinks) +### + +cat >input < $GIT_COMMITTER_DATE +data 12 +sub_initial +M 100644 :1 file + +blob +mark :3 +data < $GIT_COMMITTER_DATE +data 8 +initial +from refs/heads/master +M 100644 :3 .gitmodules +M 160000 :2 sub + +blob +mark :5 +data 20 +test file +more data + +commit refs/heads/sub +mark :6 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 11 +sub_second +from :2 +M 100644 :5 file + +commit refs/heads/subuse1 +mark :7 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 7 +second +from :4 +M 160000 :6 sub + +INPUT_END + +test_expect_success \ + 'P: supermodule & submodule mix' \ + 'git-fast-import input < $GIT_COMMITTER_DATE +data 8 +initial +from refs/heads/master +M 100644 :1 .gitmodules +M 160000 $SUBPREV sub + +commit refs/heads/subuse2 +mark :3 +committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE +data 7 +second +from :2 +M 160000 $SUBLAST sub + +INPUT_END + +test_expect_success \ + 'P: verbatim SHA gitlinks' \ + 'git branch -D sub && + git gc && git prune && + git-fast-import input < $GIT_COMMITTER_DATE +data <input < $GIT_COMMITTER_DATE +data < file && + git add file && + git commit -m sub_initial && + cd .. && + git submodule add "`pwd`/sub" sub && + git commit -m initial && + test_tick && + cd sub && + echo more data >> file && + git add file && + git commit -m sub_second && + cd .. && + git add sub && + git commit -m second + +' + +test_expect_success 'submodule fast-export | fast-import' ' + + SUBENT1=$(git ls-tree master^ sub) && + SUBENT2=$(git ls-tree master sub) && + rm -rf new && + mkdir new && + git --git-dir=new/.git init && + git fast-export --signed-tags=strip --all | + (cd new && + git fast-import && + test "$SUBENT1" = "$(git ls-tree refs/heads/master^ sub)" && + test "$SUBENT2" = "$(git ls-tree refs/heads/master sub)" && + git checkout master && + git submodule init && + git submodule update && + cmp sub/file ../sub/file) + +' + test_done diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh index e97aaa6c2a..d49f0df8c4 100755 --- a/t/t9400-git-cvsserver-server.sh +++ b/t/t9400-git-cvsserver-server.sh @@ -470,4 +470,15 @@ test_expect_success 'cvs status (no subdirs in header)' ' ! grep / <../out ' +#------------ +# CVS CHECKOUT +#------------ + +cd "$WORKDIR" +test_expect_success 'cvs co -c (shows module database)' ' + GIT_CONFIG="$git_config" cvs co -c > out && + grep "^master[ ]\+master$" < out && + ! grep -v "^master[ ]\+master$" < out +' + test_done diff --git a/t/t9600-cvsimport.sh b/t/t9600-cvsimport.sh index 1e01e5c748..0d7786a8c7 100755 --- a/t/t9600-cvsimport.sh +++ b/t/t9600-cvsimport.sh @@ -5,6 +5,7 @@ test_description='git-cvsimport basic tests' CVSROOT=$(pwd)/cvsroot export CVSROOT +unset CVS_SERVER # for clean cvsps cache HOME=$(pwd) export HOME