Skip to content

Commit ca3ef81

Browse files
committed
Merge branch 'cb/common-prefix-unification'
* cb/common-prefix-unification: rename pathspec_prefix() to common_prefix() and move to dir.[ch] consolidate pathspec_prefix and common_prefix remove prefix argument from pathspec_prefix
2 parents 9488c18 + f950eb9 commit ca3ef81

File tree

6 files changed

+40
-64
lines changed

6 files changed

+40
-64
lines changed

builtin/commit.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,8 +255,9 @@ static int list_paths(struct string_list *list, const char *with_tree,
255255
m = xcalloc(1, i);
256256

257257
if (with_tree) {
258-
const char *max_prefix = pathspec_prefix(prefix, pattern);
259-
overlay_tree_on_cache(with_tree, max_prefix);
258+
char *max_prefix = common_prefix(pattern);
259+
overlay_tree_on_cache(with_tree, max_prefix ? max_prefix : prefix);
260+
free(max_prefix);
260261
}
261262

262263
for (i = 0; i < active_nr; i++) {

builtin/ls-files.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix)
545545
strip_trailing_slash_from_submodules();
546546

547547
/* Find common prefix for all pathspec's */
548-
max_prefix = pathspec_prefix(prefix, pathspec);
548+
max_prefix = common_prefix(pathspec);
549549
max_prefix_len = max_prefix ? strlen(max_prefix) : 0;
550550

551551
/* Treat unmatching pathspec elements as errors */

cache.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,6 @@ extern void set_git_work_tree(const char *tree);
445445
#define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
446446

447447
extern const char **get_pathspec(const char *prefix, const char **pathspec);
448-
extern const char *pathspec_prefix(const char *prefix, const char **pathspec);
449448
extern void setup_work_tree(void);
450449
extern const char *setup_git_directory_gently(int *);
451450
extern const char *setup_git_directory(void);

dir.c

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -34,56 +34,63 @@ int fnmatch_icase(const char *pattern, const char *string, int flags)
3434
return fnmatch(pattern, string, flags | (ignore_case ? FNM_CASEFOLD : 0));
3535
}
3636

37-
static int common_prefix(const char **pathspec)
37+
static size_t common_prefix_len(const char **pathspec)
3838
{
39-
const char *path, *slash, *next;
40-
int prefix;
39+
const char *n, *first;
40+
size_t max = 0;
4141

4242
if (!pathspec)
43-
return 0;
43+
return max;
44+
45+
first = *pathspec;
46+
while ((n = *pathspec++)) {
47+
size_t i, len = 0;
48+
for (i = 0; first == n || i < max; i++) {
49+
char c = n[i];
50+
if (!c || c != first[i] || is_glob_special(c))
51+
break;
52+
if (c == '/')
53+
len = i + 1;
54+
}
55+
if (first == n || len < max) {
56+
max = len;
57+
if (!max)
58+
break;
59+
}
60+
}
61+
return max;
62+
}
4463

45-
path = *pathspec;
46-
slash = strrchr(path, '/');
47-
if (!slash)
48-
return 0;
64+
/*
65+
* Returns a copy of the longest leading path common among all
66+
* pathspecs.
67+
*/
68+
char *common_prefix(const char **pathspec)
69+
{
70+
unsigned long len = common_prefix_len(pathspec);
4971

50-
/*
51-
* The first 'prefix' characters of 'path' are common leading
52-
* path components among the pathspecs we have seen so far,
53-
* including the trailing slash.
54-
*/
55-
prefix = slash - path + 1;
56-
while ((next = *++pathspec) != NULL) {
57-
int len, last_matching_slash = -1;
58-
for (len = 0; len < prefix && next[len] == path[len]; len++)
59-
if (next[len] == '/')
60-
last_matching_slash = len;
61-
if (len == prefix)
62-
continue;
63-
if (last_matching_slash < 0)
64-
return 0;
65-
prefix = last_matching_slash + 1;
66-
}
67-
return prefix;
72+
return len ? xmemdupz(*pathspec, len) : NULL;
6873
}
6974

7075
int fill_directory(struct dir_struct *dir, const char **pathspec)
7176
{
7277
const char *path;
73-
int len;
78+
size_t len;
7479

7580
/*
7681
* Calculate common prefix for the pathspec, and
7782
* use that to optimize the directory walk
7883
*/
79-
len = common_prefix(pathspec);
84+
len = common_prefix_len(pathspec);
8085
path = "";
8186

8287
if (len)
8388
path = xmemdupz(*pathspec, len);
8489

8590
/* Read the directory and prune it */
8691
read_directory(dir, path, len, pathspec);
92+
if (*path)
93+
free((char *)path);
8794
return len;
8895
}
8996

dir.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ struct dir_struct {
6464
#define MATCHED_RECURSIVELY 1
6565
#define MATCHED_FNMATCH 2
6666
#define MATCHED_EXACTLY 3
67+
extern char *common_prefix(const char **pathspec);
6768
extern int match_pathspec(const char **pathspec, const char *name, int namelen, int prefix, char *seen);
6869
extern int match_pathspec_depth(const struct pathspec *pathspec,
6970
const char *name, int namelen,

setup.c

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -236,38 +236,6 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
236236
return pathspec;
237237
}
238238

239-
const char *pathspec_prefix(const char *prefix, const char **pathspec)
240-
{
241-
const char **p, *n, *prev;
242-
unsigned long max;
243-
244-
if (!pathspec)
245-
return prefix ? xmemdupz(prefix, strlen(prefix)) : NULL;
246-
247-
prev = NULL;
248-
max = PATH_MAX;
249-
for (p = pathspec; (n = *p) != NULL; p++) {
250-
int i, len = 0;
251-
for (i = 0; i < max; i++) {
252-
char c = n[i];
253-
if (prev && prev[i] != c)
254-
break;
255-
if (!c || c == '*' || c == '?')
256-
break;
257-
if (c == '/')
258-
len = i+1;
259-
}
260-
prev = n;
261-
if (len < max) {
262-
max = len;
263-
if (!max)
264-
break;
265-
}
266-
}
267-
268-
return max ? xmemdupz(prev, max) : NULL;
269-
}
270-
271239
/*
272240
* Test if it looks like we're at a git directory.
273241
* We want to see:

0 commit comments

Comments
 (0)