Skip to content

Commit

Permalink
Merge branch 'jl/submodule-mv'
Browse files Browse the repository at this point in the history
"git mv A B" when moving a submodule A does "the right thing",
inclusing relocating its working tree and adjusting the paths in
the .gitmodules file.

* jl/submodule-mv: (53 commits)
  rm: delete .gitmodules entry of submodules removed from the work tree
  mv: update the path entry in .gitmodules for moved submodules
  submodule.c: add .gitmodules staging helper functions
  mv: move submodules using a gitfile
  mv: move submodules together with their work trees
  rm: do not set a variable twice without intermediate reading.
  t6131 - skip tests if on case-insensitive file system
  parse_pathspec: accept :(icase)path syntax
  pathspec: support :(glob) syntax
  pathspec: make --literal-pathspecs disable pathspec magic
  pathspec: support :(literal) syntax for noglob pathspec
  kill limit_pathspec_to_literal() as it's only used by parse_pathspec()
  parse_pathspec: preserve prefix length via PATHSPEC_PREFIX_ORIGIN
  parse_pathspec: make sure the prefix part is wildcard-free
  rename field "raw" to "_raw" in struct pathspec
  tree-diff: remove the use of pathspec's raw[] in follow-rename codepath
  remove match_pathspec() in favor of match_pathspec_depth()
  remove init_pathspec() in favor of parse_pathspec()
  remove diff_tree_{setup,release}_paths
  convert common_prefix() to use struct pathspec
  ...
  • Loading branch information
gitster committed Sep 9, 2013
2 parents de9a253 + 95c1641 commit b02f5ae
Show file tree
Hide file tree
Showing 62 changed files with 1,891 additions and 881 deletions.
10 changes: 9 additions & 1 deletion Documentation/git-mv.txt
Expand Up @@ -13,7 +13,7 @@ SYNOPSIS


DESCRIPTION DESCRIPTION
----------- -----------
This script is used to move or rename a file, directory or symlink. Move or rename a file, directory or symlink.


git mv [-v] [-f] [-n] [-k] <source> <destination> git mv [-v] [-f] [-n] [-k] <source> <destination>
git mv [-v] [-f] [-n] [-k] <source> ... <destination directory> git mv [-v] [-f] [-n] [-k] <source> ... <destination directory>
Expand Down Expand Up @@ -44,6 +44,14 @@ OPTIONS
--verbose:: --verbose::
Report the names of files as they are moved. Report the names of files as they are moved.


SUBMODULES
----------
Moving a submodule using a gitfile (which means they were cloned
with a Git version 1.7.8 or newer) will update the gitfile and
core.worktree setting to make the submodule work in the new location.
It also will attempt to update the submodule.<name>.path setting in
the linkgit:gitmodules[5] file and stage that file (unless -n is used).

GIT GIT
--- ---
Part of the linkgit:git[1] suite Part of the linkgit:git[1] suite
8 changes: 5 additions & 3 deletions Documentation/git-rm.txt
Expand Up @@ -134,14 +134,16 @@ use the following command:
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached
---------------- ----------------


Submodules SUBMODULES
~~~~~~~~~~ ----------
Only submodules using a gitfile (which means they were cloned Only submodules using a gitfile (which means they were cloned
with a Git version 1.7.8 or newer) will be removed from the work with a Git version 1.7.8 or newer) will be removed from the work
tree, as their repository lives inside the .git directory of the tree, as their repository lives inside the .git directory of the
superproject. If a submodule (or one of those nested inside it) superproject. If a submodule (or one of those nested inside it)
still uses a .git directory, `git rm` will fail - no matter if forced still uses a .git directory, `git rm` will fail - no matter if forced
or not - to protect the submodule's history. or not - to protect the submodule's history. If it exists the
submodule.<name> section in the linkgit:gitmodules[5] file will also
be removed and that file will be staged (unless --cached or -n are used).


A submodule is considered up-to-date when the HEAD is the same as A submodule is considered up-to-date when the HEAD is the same as
recorded in the index, no tracked files are modified and no untracked recorded in the index, no tracked files are modified and no untracked
Expand Down
31 changes: 29 additions & 2 deletions Documentation/git.txt
Expand Up @@ -457,10 +457,25 @@ help ...`.
linkgit:git-replace[1] for more information. linkgit:git-replace[1] for more information.


--literal-pathspecs:: --literal-pathspecs::
Treat pathspecs literally, rather than as glob patterns. This is Treat pathspecs literally (i.e. no globbing, no pathspec magic).
equivalent to setting the `GIT_LITERAL_PATHSPECS` environment This is equivalent to setting the `GIT_LITERAL_PATHSPECS` environment
variable to `1`. variable to `1`.


--glob-pathspecs:
Add "glob" magic to all pathspec. This is equivalent to setting
the `GIT_GLOB_PATHSPECS` environment variable to `1`. Disabling
globbing on individual pathspecs can be done using pathspec
magic ":(literal)"

--noglob-pathspecs:
Add "literal" magic to all pathspec. This is equivalent to setting
the `GIT_NOGLOB_PATHSPECS` environment variable to `1`. Enabling
globbing on individual pathspecs can be done using pathspec
magic ":(glob)"

--icase-pathspecs:
Add "icase" magic to all pathspec. This is equivalent to setting
the `GIT_ICASE_PATHSPECS` environment variable to `1`.


GIT COMMANDS GIT COMMANDS
------------ ------------
Expand Down Expand Up @@ -867,6 +882,18 @@ GIT_LITERAL_PATHSPECS::
literal paths to Git (e.g., paths previously given to you by literal paths to Git (e.g., paths previously given to you by
`git ls-tree`, `--raw` diff output, etc). `git ls-tree`, `--raw` diff output, etc).


GIT_GLOB_PATHSPECS::
Setting this variable to `1` will cause Git to treat all
pathspecs as glob patterns (aka "glob" magic).

GIT_NOGLOB_PATHSPECS::
Setting this variable to `1` will cause Git to treat all
pathspecs as literal (aka "literal" magic).

GIT_ICASE_PATHSPECS::
Setting this variable to `1` will cause Git to treat all
pathspecs as case-insensitive.



Discussion[[Discussion]] Discussion[[Discussion]]
------------------------ ------------------------
Expand Down
52 changes: 48 additions & 4 deletions Documentation/glossary-content.txt
Expand Up @@ -322,10 +322,54 @@ and a close parentheses `)`, and the remainder is the pattern to match
against the path. against the path.
+ +
The "magic signature" consists of an ASCII symbol that is not The "magic signature" consists of an ASCII symbol that is not
alphanumeric. Currently only the slash `/` is recognized as a alphanumeric.
"magic signature": it makes the pattern match from the root of +
the working tree, even when you are running the command from --
inside a subdirectory. top `/`;;
The magic word `top` (mnemonic: `/`) makes the pattern match
from the root of the working tree, even when you are running
the command from inside a subdirectory.

literal;;
Wildcards in the pattern such as `*` or `?` are treated
as literal characters.

icase;;
Case insensitive match.

glob;;
Git treats the pattern as a shell glob suitable for
consumption by fnmatch(3) with the FNM_PATHNAME flag:
wildcards in the pattern will not match a / in the pathname.
For example, "Documentation/{asterisk}.html" matches
"Documentation/git.html" but not "Documentation/ppc/ppc.html"
or "tools/perf/Documentation/perf.html".
+
Two consecutive asterisks ("`**`") in patterns matched against
full pathname may have special meaning:

- A leading "`**`" followed by a slash means match in all
directories. For example, "`**/foo`" matches file or directory
"`foo`" anywhere, the same as pattern "`foo`". "**/foo/bar"
matches file or directory "`bar`" anywhere that is directly
under directory "`foo`".

- A trailing "/**" matches everything inside. For example,
"abc/**" matches all files inside directory "abc", relative
to the location of the `.gitignore` file, with infinite depth.

- A slash followed by two consecutive asterisks then a slash
matches zero or more directories. For example, "`a/**/b`"
matches "`a/b`", "`a/x/b`", "`a/x/y/b`" and so on.

- Other consecutive asterisks are considered invalid.
+
Glob magic is incompatible with literal magic.
--
+
Currently only the slash `/` is recognized as the "magic signature",
but it is envisioned that we will support more types of magic in later
versions of Git.
+ +
A pathspec with only a colon means "there is no pathspec". This form A pathspec with only a colon means "there is no pathspec". This form
should not be combined with other pathspec. should not be combined with other pathspec.
Expand Down
38 changes: 37 additions & 1 deletion Documentation/technical/api-setup.txt
Expand Up @@ -8,6 +8,42 @@ Talk about
* is_inside_git_dir() * is_inside_git_dir()
* is_inside_work_tree() * is_inside_work_tree()
* setup_work_tree() * setup_work_tree()
* get_pathspec()


(Dscho) (Dscho)

Pathspec
--------

See glossary-context.txt for the syntax of pathspec. In memory, a
pathspec set is represented by "struct pathspec" and is prepared by
parse_pathspec(). This function takes several arguments:

- magic_mask specifies what features that are NOT supported by the
following code. If a user attempts to use such a feature,
parse_pathspec() can reject it early.

- flags specifies other things that the caller wants parse_pathspec to
perform.

- prefix and args come from cmd_* functions

get_pathspec() is obsolete and should never be used in new code.

parse_pathspec() helps catch unsupported features and reject them
politely. At a lower level, different pathspec-related functions may
not support the same set of features. Such pathspec-sensitive
functions are guarded with GUARD_PATHSPEC(), which will die in an
unfriendly way when an unsupported feature is requested.

The command designers are supposed to make sure that GUARD_PATHSPEC()
never dies. They have to make sure all unsupported features are caught
by parse_pathspec(), not by GUARD_PATHSPEC. grepping GUARD_PATHSPEC()
should give the designers all pathspec-sensitive codepaths and what
features they support.

A similar process is applied when a new pathspec magic is added. The
designer lifts the GUARD_PATHSPEC restriction in the functions that
support the new magic. At the same time (s)he has to make sure this
new feature will be caught at parse_pathspec() in commands that cannot
handle the new magic in some cases. grepping parse_pathspec() should
help.
18 changes: 11 additions & 7 deletions archive.c
Expand Up @@ -151,7 +151,6 @@ int write_archive_entries(struct archiver_args *args,
struct archiver_context context; struct archiver_context context;
struct unpack_trees_options opts; struct unpack_trees_options opts;
struct tree_desc t; struct tree_desc t;
struct pathspec pathspec;
int err; int err;


if (args->baselen > 0 && args->base[args->baselen - 1] == '/') { if (args->baselen > 0 && args->base[args->baselen - 1] == '/') {
Expand Down Expand Up @@ -186,10 +185,8 @@ int write_archive_entries(struct archiver_args *args,
git_attr_set_direction(GIT_ATTR_INDEX, &the_index); git_attr_set_direction(GIT_ATTR_INDEX, &the_index);
} }


init_pathspec(&pathspec, args->pathspec); err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec,
err = read_tree_recursive(args->tree, "", 0, 0, &pathspec,
write_archive_entry, &context); write_archive_entry, &context);
free_pathspec(&pathspec);
if (err == READ_TREE_RECURSIVE) if (err == READ_TREE_RECURSIVE)
err = 0; err = 0;
return err; return err;
Expand Down Expand Up @@ -222,7 +219,7 @@ static int path_exists(struct tree *tree, const char *path)
struct pathspec pathspec; struct pathspec pathspec;
int ret; int ret;


init_pathspec(&pathspec, paths); parse_pathspec(&pathspec, 0, 0, "", paths);
ret = read_tree_recursive(tree, "", 0, 0, &pathspec, reject_entry, NULL); ret = read_tree_recursive(tree, "", 0, 0, &pathspec, reject_entry, NULL);
free_pathspec(&pathspec); free_pathspec(&pathspec);
return ret != 0; return ret != 0;
Expand All @@ -231,11 +228,18 @@ static int path_exists(struct tree *tree, const char *path)
static void parse_pathspec_arg(const char **pathspec, static void parse_pathspec_arg(const char **pathspec,
struct archiver_args *ar_args) struct archiver_args *ar_args)
{ {
ar_args->pathspec = pathspec = get_pathspec("", pathspec); /*
* must be consistent with parse_pathspec in path_exists()
* Also if pathspec patterns are dependent, we're in big
* trouble as we test each one separately
*/
parse_pathspec(&ar_args->pathspec, 0,
PATHSPEC_PREFER_FULL,
"", pathspec);
if (pathspec) { if (pathspec) {
while (*pathspec) { while (*pathspec) {
if (**pathspec && !path_exists(ar_args->tree, *pathspec)) if (**pathspec && !path_exists(ar_args->tree, *pathspec))
die("path not found: %s", *pathspec); die(_("pathspec '%s' did not match any files"), *pathspec);
pathspec++; pathspec++;
} }
} }
Expand Down
4 changes: 3 additions & 1 deletion archive.h
@@ -1,14 +1,16 @@
#ifndef ARCHIVE_H #ifndef ARCHIVE_H
#define ARCHIVE_H #define ARCHIVE_H


#include "pathspec.h"

struct archiver_args { struct archiver_args {
const char *base; const char *base;
size_t baselen; size_t baselen;
struct tree *tree; struct tree *tree;
const unsigned char *commit_sha1; const unsigned char *commit_sha1;
const struct commit *commit; const struct commit *commit;
time_t time; time_t time;
const char **pathspec; struct pathspec pathspec;
unsigned int verbose : 1; unsigned int verbose : 1;
unsigned int worktree_attributes : 1; unsigned int worktree_attributes : 1;
unsigned int convert : 1; unsigned int convert : 1;
Expand Down

0 comments on commit b02f5ae

Please sign in to comment.