Skip to content

Commit b3b2ddc

Browse files
committed
Merge branch 'ds/bundle-uri'
Preliminary code refactoring around transport and bundle code. * ds/bundle-uri: bundle.h: make "fd" version of read_bundle_header() public remote: allow relative_url() to return an absolute url remote: move relative_url() http: make http_get_file() external fetch-pack: move --keep=* option filling to a function fetch-pack: add a deref_without_lazy_fetch_extended() dir API: add a generalized path_match_flags() function connect.c: refactor sending of agent & object-format
2 parents 83937e9 + 89c6e45 commit b3b2ddc

File tree

17 files changed

+321
-191
lines changed

17 files changed

+321
-191
lines changed

builtin/submodule--helper.c

Lines changed: 12 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -72,135 +72,6 @@ static char *get_default_remote(void)
7272
return repo_get_default_remote(the_repository);
7373
}
7474

75-
static int starts_with_dot_slash(const char *str)
76-
{
77-
return str[0] == '.' && is_dir_sep(str[1]);
78-
}
79-
80-
static int starts_with_dot_dot_slash(const char *str)
81-
{
82-
return str[0] == '.' && str[1] == '.' && is_dir_sep(str[2]);
83-
}
84-
85-
/*
86-
* Returns 1 if it was the last chop before ':'.
87-
*/
88-
static int chop_last_dir(char **remoteurl, int is_relative)
89-
{
90-
char *rfind = find_last_dir_sep(*remoteurl);
91-
if (rfind) {
92-
*rfind = '\0';
93-
return 0;
94-
}
95-
96-
rfind = strrchr(*remoteurl, ':');
97-
if (rfind) {
98-
*rfind = '\0';
99-
return 1;
100-
}
101-
102-
if (is_relative || !strcmp(".", *remoteurl))
103-
die(_("cannot strip one component off url '%s'"),
104-
*remoteurl);
105-
106-
free(*remoteurl);
107-
*remoteurl = xstrdup(".");
108-
return 0;
109-
}
110-
111-
/*
112-
* The `url` argument is the URL that navigates to the submodule origin
113-
* repo. When relative, this URL is relative to the superproject origin
114-
* URL repo. The `up_path` argument, if specified, is the relative
115-
* path that navigates from the submodule working tree to the superproject
116-
* working tree. Returns the origin URL of the submodule.
117-
*
118-
* Return either an absolute URL or filesystem path (if the superproject
119-
* origin URL is an absolute URL or filesystem path, respectively) or a
120-
* relative file system path (if the superproject origin URL is a relative
121-
* file system path).
122-
*
123-
* When the output is a relative file system path, the path is either
124-
* relative to the submodule working tree, if up_path is specified, or to
125-
* the superproject working tree otherwise.
126-
*
127-
* NEEDSWORK: This works incorrectly on the domain and protocol part.
128-
* remote_url url outcome expectation
129-
* http://a.com/b ../c http://a.com/c as is
130-
* http://a.com/b/ ../c http://a.com/c same as previous line, but
131-
* ignore trailing slash in url
132-
* http://a.com/b ../../c http://c error out
133-
* http://a.com/b ../../../c http:/c error out
134-
* http://a.com/b ../../../../c http:c error out
135-
* http://a.com/b ../../../../../c .:c error out
136-
* NEEDSWORK: Given how chop_last_dir() works, this function is broken
137-
* when a local part has a colon in its path component, too.
138-
*/
139-
static char *relative_url(const char *remote_url,
140-
const char *url,
141-
const char *up_path)
142-
{
143-
int is_relative = 0;
144-
int colonsep = 0;
145-
char *out;
146-
char *remoteurl = xstrdup(remote_url);
147-
struct strbuf sb = STRBUF_INIT;
148-
size_t len = strlen(remoteurl);
149-
150-
if (is_dir_sep(remoteurl[len-1]))
151-
remoteurl[len-1] = '\0';
152-
153-
if (!url_is_local_not_ssh(remoteurl) || is_absolute_path(remoteurl))
154-
is_relative = 0;
155-
else {
156-
is_relative = 1;
157-
/*
158-
* Prepend a './' to ensure all relative
159-
* remoteurls start with './' or '../'
160-
*/
161-
if (!starts_with_dot_slash(remoteurl) &&
162-
!starts_with_dot_dot_slash(remoteurl)) {
163-
strbuf_reset(&sb);
164-
strbuf_addf(&sb, "./%s", remoteurl);
165-
free(remoteurl);
166-
remoteurl = strbuf_detach(&sb, NULL);
167-
}
168-
}
169-
/*
170-
* When the url starts with '../', remove that and the
171-
* last directory in remoteurl.
172-
*/
173-
while (url) {
174-
if (starts_with_dot_dot_slash(url)) {
175-
url += 3;
176-
colonsep |= chop_last_dir(&remoteurl, is_relative);
177-
} else if (starts_with_dot_slash(url))
178-
url += 2;
179-
else
180-
break;
181-
}
182-
strbuf_reset(&sb);
183-
strbuf_addf(&sb, "%s%s%s", remoteurl, colonsep ? ":" : "/", url);
184-
if (ends_with(url, "/"))
185-
strbuf_setlen(&sb, sb.len - 1);
186-
free(remoteurl);
187-
188-
if (starts_with_dot_slash(sb.buf))
189-
out = xstrdup(sb.buf + 2);
190-
else
191-
out = xstrdup(sb.buf);
192-
193-
if (!up_path || !is_relative) {
194-
strbuf_release(&sb);
195-
return out;
196-
}
197-
198-
strbuf_reset(&sb);
199-
strbuf_addf(&sb, "%s%s", up_path, out);
200-
free(out);
201-
return strbuf_detach(&sb, NULL);
202-
}
203-
20475
static char *resolve_relative_url(const char *rel_url, const char *up_path, int quiet)
20576
{
20677
char *remoteurl, *resolved_url;
@@ -592,6 +463,18 @@ static int module_foreach(int argc, const char **argv, const char *prefix)
592463
return 0;
593464
}
594465

466+
static int starts_with_dot_slash(const char *const path)
467+
{
468+
return path_match_flags(path, PATH_MATCH_STARTS_WITH_DOT_SLASH |
469+
PATH_MATCH_XPLATFORM);
470+
}
471+
472+
static int starts_with_dot_dot_slash(const char *const path)
473+
{
474+
return path_match_flags(path, PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH |
475+
PATH_MATCH_XPLATFORM);
476+
}
477+
595478
struct init_cb {
596479
const char *prefix;
597480
const char *superprefix;

bundle.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ static int parse_bundle_signature(struct bundle_header *header, const char *line
6666
return -1;
6767
}
6868

69-
static int parse_bundle_header(int fd, struct bundle_header *header,
70-
const char *report_path)
69+
int read_bundle_header_fd(int fd, struct bundle_header *header,
70+
const char *report_path)
7171
{
7272
struct strbuf buf = STRBUF_INIT;
7373
int status = 0;
@@ -143,7 +143,7 @@ int read_bundle_header(const char *path, struct bundle_header *header)
143143

144144
if (fd < 0)
145145
return error(_("could not open '%s'"), path);
146-
return parse_bundle_header(fd, header, path);
146+
return read_bundle_header_fd(fd, header, path);
147147
}
148148

149149
int is_bundle(const char *path, int quiet)
@@ -153,7 +153,7 @@ int is_bundle(const char *path, int quiet)
153153

154154
if (fd < 0)
155155
return 0;
156-
fd = parse_bundle_header(fd, &header, quiet ? NULL : path);
156+
fd = read_bundle_header_fd(fd, &header, quiet ? NULL : path);
157157
if (fd >= 0)
158158
close(fd);
159159
bundle_header_release(&header);

bundle.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ void bundle_header_release(struct bundle_header *header);
2424

2525
int is_bundle(const char *path, int quiet);
2626
int read_bundle_header(const char *path, struct bundle_header *header);
27+
int read_bundle_header_fd(int fd, struct bundle_header *header,
28+
const char *report_path);
2729
int create_bundle(struct repository *r, const char *path,
2830
int argc, const char **argv, struct strvec *pack_options,
2931
int version);

compat/mingw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2830,7 +2830,7 @@ int is_valid_win32_path(const char *path, int allow_literal_nul)
28302830
}
28312831

28322832
c = path[i];
2833-
if (c && c != '.' && c != ':' && c != '/' && c != '\\')
2833+
if (c && c != '.' && c != ':' && !is_xplatform_dir_sep(c))
28342834
goto not_a_reserved_name;
28352835

28362836
/* contains reserved name */

compat/win32/path-utils.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@ int win32_has_dos_drive_prefix(const char *path);
66

77
int win32_skip_dos_drive_prefix(char **path);
88
#define skip_dos_drive_prefix win32_skip_dos_drive_prefix
9-
static inline int win32_is_dir_sep(int c)
10-
{
11-
return c == '/' || c == '\\';
12-
}
13-
#define is_dir_sep win32_is_dir_sep
9+
#define is_dir_sep is_xplatform_dir_sep
1410
static inline char *win32_find_last_dir_sep(const char *path)
1511
{
1612
char *ret = NULL;

connect.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -473,14 +473,31 @@ void check_stateless_delimiter(int stateless_rpc,
473473
die("%s", error);
474474
}
475475

476+
static void send_capabilities(int fd_out, struct packet_reader *reader)
477+
{
478+
const char *hash_name;
479+
480+
if (server_supports_v2("agent", 0))
481+
packet_write_fmt(fd_out, "agent=%s", git_user_agent_sanitized());
482+
483+
if (server_feature_v2("object-format", &hash_name)) {
484+
int hash_algo = hash_algo_by_name(hash_name);
485+
if (hash_algo == GIT_HASH_UNKNOWN)
486+
die(_("unknown object format '%s' specified by server"), hash_name);
487+
reader->hash_algo = &hash_algos[hash_algo];
488+
packet_write_fmt(fd_out, "object-format=%s", reader->hash_algo->name);
489+
} else {
490+
reader->hash_algo = &hash_algos[GIT_HASH_SHA1];
491+
}
492+
}
493+
476494
struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
477495
struct ref **list, int for_push,
478496
struct transport_ls_refs_options *transport_options,
479497
const struct string_list *server_options,
480498
int stateless_rpc)
481499
{
482500
int i;
483-
const char *hash_name;
484501
struct strvec *ref_prefixes = transport_options ?
485502
&transport_options->ref_prefixes : NULL;
486503
const char **unborn_head_target = transport_options ?
@@ -490,18 +507,8 @@ struct ref **get_remote_refs(int fd_out, struct packet_reader *reader,
490507
if (server_supports_v2("ls-refs", 1))
491508
packet_write_fmt(fd_out, "command=ls-refs\n");
492509

493-
if (server_supports_v2("agent", 0))
494-
packet_write_fmt(fd_out, "agent=%s", git_user_agent_sanitized());
495-
496-
if (server_feature_v2("object-format", &hash_name)) {
497-
int hash_algo = hash_algo_by_name(hash_name);
498-
if (hash_algo == GIT_HASH_UNKNOWN)
499-
die(_("unknown object format '%s' specified by server"), hash_name);
500-
reader->hash_algo = &hash_algos[hash_algo];
501-
packet_write_fmt(fd_out, "object-format=%s", reader->hash_algo->name);
502-
} else {
503-
reader->hash_algo = &hash_algos[GIT_HASH_SHA1];
504-
}
510+
/* Send capabilities */
511+
send_capabilities(fd_out, reader);
505512

506513
if (server_options && server_options->nr &&
507514
server_supports_v2("server-option", 1))

dir.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3955,3 +3955,32 @@ void relocate_gitdir(const char *path, const char *old_git_dir, const char *new_
39553955

39563956
connect_work_tree_and_git_dir(path, new_git_dir, 0);
39573957
}
3958+
3959+
int path_match_flags(const char *const str, const enum path_match_flags flags)
3960+
{
3961+
const char *p = str;
3962+
3963+
if (flags & PATH_MATCH_NATIVE &&
3964+
flags & PATH_MATCH_XPLATFORM)
3965+
BUG("path_match_flags() must get one match kind, not multiple!");
3966+
else if (!(flags & PATH_MATCH_KINDS_MASK))
3967+
BUG("path_match_flags() must get at least one match kind!");
3968+
3969+
if (flags & PATH_MATCH_STARTS_WITH_DOT_SLASH &&
3970+
flags & PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH)
3971+
BUG("path_match_flags() must get one platform kind, not multiple!");
3972+
else if (!(flags & PATH_MATCH_PLATFORM_MASK))
3973+
BUG("path_match_flags() must get at least one platform kind!");
3974+
3975+
if (*p++ != '.')
3976+
return 0;
3977+
if (flags & PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH &&
3978+
*p++ != '.')
3979+
return 0;
3980+
3981+
if (flags & PATH_MATCH_NATIVE)
3982+
return is_dir_sep(*p);
3983+
else if (flags & PATH_MATCH_XPLATFORM)
3984+
return is_xplatform_dir_sep(*p);
3985+
BUG("unreachable");
3986+
}

dir.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,4 +578,67 @@ void connect_work_tree_and_git_dir(const char *work_tree,
578578
void relocate_gitdir(const char *path,
579579
const char *old_git_dir,
580580
const char *new_git_dir);
581+
582+
/**
583+
* The "enum path_matches_kind" determines how path_match_flags() will
584+
* behave. The flags come in sets, and one (and only one) must be
585+
* provided out of each "set":
586+
*
587+
* PATH_MATCH_NATIVE:
588+
* Path separator is is_dir_sep()
589+
* PATH_MATCH_XPLATFORM:
590+
* Path separator is is_xplatform_dir_sep()
591+
*
592+
* Do we use is_dir_sep() to check for a directory separator
593+
* (*_NATIVE), or do we always check for '/' or '\' (*_XPLATFORM). The
594+
* "*_NATIVE" version on Windows is the same as "*_XPLATFORM",
595+
* everywhere else "*_NATIVE" means "only /".
596+
*
597+
* PATH_MATCH_STARTS_WITH_DOT_SLASH:
598+
* Match a path starting with "./"
599+
* PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH:
600+
* Match a path starting with "../"
601+
*
602+
* The "/" in the above is adjusted based on the "*_NATIVE" and
603+
* "*_XPLATFORM" flags.
604+
*/
605+
enum path_match_flags {
606+
PATH_MATCH_NATIVE = 1 << 0,
607+
PATH_MATCH_XPLATFORM = 1 << 1,
608+
PATH_MATCH_STARTS_WITH_DOT_SLASH = 1 << 2,
609+
PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH = 1 << 3,
610+
};
611+
#define PATH_MATCH_KINDS_MASK (PATH_MATCH_STARTS_WITH_DOT_SLASH | \
612+
PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH)
613+
#define PATH_MATCH_PLATFORM_MASK (PATH_MATCH_NATIVE | PATH_MATCH_XPLATFORM)
614+
615+
/**
616+
* path_match_flags() checks if a given "path" matches a given "enum
617+
* path_match_flags" criteria.
618+
*/
619+
int path_match_flags(const char *const path, const enum path_match_flags f);
620+
621+
/**
622+
* starts_with_dot_slash_native(): convenience wrapper for
623+
* path_match_flags() with PATH_MATCH_STARTS_WITH_DOT_SLASH and
624+
* PATH_MATCH_NATIVE.
625+
*/
626+
static inline int starts_with_dot_slash_native(const char *const path)
627+
{
628+
const enum path_match_flags what = PATH_MATCH_STARTS_WITH_DOT_SLASH;
629+
630+
return path_match_flags(path, what | PATH_MATCH_NATIVE);
631+
}
632+
633+
/**
634+
* starts_with_dot_slash_native(): convenience wrapper for
635+
* path_match_flags() with PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH and
636+
* PATH_MATCH_NATIVE.
637+
*/
638+
static inline int starts_with_dot_dot_slash_native(const char *const path)
639+
{
640+
const enum path_match_flags what = PATH_MATCH_STARTS_WITH_DOT_DOT_SLASH;
641+
642+
return path_match_flags(path, what | PATH_MATCH_NATIVE);
643+
}
581644
#endif

0 commit comments

Comments
 (0)