Re: [PATCH] commit: allow partial commits with relative paths
- From
Michael J Gruber <git@drmicha.warpmail.net>
- Date
- Jul 30, 2011, 16:45 UTC
- Message-ID
- <4E343534.8000604@drmicha.warpmail.net>
- In-Reply-To
- <20110729133551.GA8707@toss.lan>
Clemens Buchacher venit, vidit, dixit 29.07.2011 15:35:
Show 23 quoted lines
> In order to do partial commits, git-commit overlays a tree on the > cache and checks pathspecs against the result. Currently, the overlaying > is done using "prefix" which prevents relative pathspecs with ".." and > absolute pathspec from matching when they refer to files not under > "prefix" and absent from the index, but still in the tree (i.e. files > staged for removal). > > Instead, determine the maximal common prefix for all specified > paths using the pathspec_prefix() routine from ls-files.c. Any use > of global variables is removed from pathspec_prefix() so that it > can be called from commit.c. > > Reported-by: Reuben Thomas <rrt@sc3d.org> > Analyzed-by: Michael J Gruber <git@drmicha.warpmail.net> > Signed-off-by: Clemens Buchacher <drizzd@aon.at> > > On Mon, Jul 25, 2011 at 09:42:10AM +0200, Michael J Gruber wrote: >> >> Overlay the full tree instead. > > That is one option. On the other hand, ls-files already provides > the function we need to do this properly. >
How is this huge patch more "proper" then what I proposed?
> With your permission I am stealing your commit message.
I don't care about the message but don't see the point of this patch. Using the same message certainly won't explain the difference...
Show 137 quoted lines
>
> Clemens
> ---
> builtin/commit.c | 6 ++++--
> builtin/ls-files.c | 38 ++------------------------------------
> cache.h | 1 +
> setup.c | 32 ++++++++++++++++++++++++++++++++
> 4 files changed, 39 insertions(+), 38 deletions(-)
>
> diff --git a/builtin/commit.c b/builtin/commit.c
> index a16d00b..c2db12a 100644
> --- a/builtin/commit.c
> +++ b/builtin/commit.c
> @@ -256,8 +256,10 @@ static int list_paths(struct string_list *list, const char *with_tree,
> ;
> m = xcalloc(1, i);
>
> - if (with_tree)
> - overlay_tree_on_cache(with_tree, prefix);
> + if (with_tree) {
> + const char *max_prefix = pathspec_prefix(prefix, pattern);
> + overlay_tree_on_cache(with_tree, max_prefix);
> + }
>
> for (i = 0; i < active_nr; i++) {
> struct cache_entry *ce = active_cache[i];
> diff --git a/builtin/ls-files.c b/builtin/ls-files.c
> index 72b986f..fef5642 100644
> --- a/builtin/ls-files.c
> +++ b/builtin/ls-files.c
> @@ -276,41 +276,6 @@ static void prune_cache(const char *prefix)
> active_nr = last;
> }
>
> -static const char *pathspec_prefix(const char *prefix)
> -{
> - const char **p, *n, *prev;
> - unsigned long max;
> -
> - if (!pathspec) {
> - max_prefix_len = prefix ? strlen(prefix) : 0;
> - return prefix;
> - }
> -
> - prev = NULL;
> - max = PATH_MAX;
> - for (p = pathspec; (n = *p) != NULL; p++) {
> - int i, len = 0;
> - for (i = 0; i < max; i++) {
> - char c = n[i];
> - if (prev && prev[i] != c)
> - break;
> - if (!c || c == '*' || c == '?')
> - break;
> - if (c == '/')
> - len = i+1;
> - }
> - prev = n;
> - if (len < max) {
> - max = len;
> - if (!max)
> - break;
> - }
> - }
> -
> - max_prefix_len = max;
> - return max ? xmemdupz(prev, max) : NULL;
> -}
> -
> static void strip_trailing_slash_from_submodules(void)
> {
> const char **p;
> @@ -581,7 +546,8 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
> strip_trailing_slash_from_submodules();
>
> /* Find common prefix for all pathspec's */
> - max_prefix = pathspec_prefix(prefix);
> + max_prefix = pathspec_prefix(prefix, pathspec);
> + max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
>
> /* Treat unmatching pathspec elements as errors */
> if (pathspec && error_unmatch) {
> diff --git a/cache.h b/cache.h
> index 86518fb..dd3edaa 100644
> --- a/cache.h
> +++ b/cache.h
> @@ -441,6 +441,7 @@ extern void set_git_work_tree(const char *tree);
> #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
>
> extern const char **get_pathspec(const char *prefix, const char **pathspec);
> +extern const char *pathspec_prefix(const char *prefix, const char **pathspec);
> extern void setup_work_tree(void);
> extern const char *setup_git_directory_gently(int *);
> extern const char *setup_git_directory(void);
> diff --git a/setup.c b/setup.c
> index 5ea5502..2c51a9a 100644
> --- a/setup.c
> +++ b/setup.c
> @@ -264,6 +264,38 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
> return pathspec;
> }
>
> +const char *pathspec_prefix(const char *prefix, const char **pathspec)
> +{
> + const char **p, *n, *prev;
> + unsigned long max;
> +
> + if (!pathspec)
> + return prefix ? xmemdupz(prefix, strlen(prefix)) : NULL;
> +
> + prev = NULL;
> + max = PATH_MAX;
> + for (p = pathspec; (n = *p) != NULL; p++) {
> + int i, len = 0;
> + for (i = 0; i < max; i++) {
> + char c = n[i];
> + if (prev && prev[i] != c)
> + break;
> + if (!c || c == '*' || c == '?')
> + break;
> + if (c == '/')
> + len = i+1;
> + }
> + prev = n;
> + if (len < max) {
> + max = len;
> + if (!max)
> + break;
> + }
> + }
> +
> + return max ? xmemdupz(prev, max) : NULL;
> +}
> +
> /*
> * Test if it looks like we're at a git directory.
> * We want to see: