136 lines
2.9 KiB
C
136 lines
2.9 KiB
C
#include "builtin.h"
|
|
#include "gettext.h"
|
|
#include "parse-options.h"
|
|
#include "url.h"
|
|
#include "urlmatch.h"
|
|
|
|
static const char * const builtin_url_parse_usage[] = {
|
|
N_("git url-parse [-c <component>] [--] <url>..."),
|
|
NULL
|
|
};
|
|
|
|
static char *component_arg;
|
|
|
|
static struct option builtin_url_parse_options[] = {
|
|
OPT_STRING('c', "component", &component_arg, N_("component"),
|
|
N_("which URL component to extract")),
|
|
OPT_END(),
|
|
};
|
|
|
|
enum url_component {
|
|
URL_NONE = 0,
|
|
URL_SCHEME,
|
|
URL_USER,
|
|
URL_PASSWORD,
|
|
URL_HOST,
|
|
URL_PORT,
|
|
URL_PATH,
|
|
};
|
|
|
|
static void parse_or_die(const char *url, struct url_info *info)
|
|
{
|
|
if (url_is_local_not_ssh(url)) {
|
|
if (*url == '/')
|
|
die("'%s' is not a URL; if you meant a local "
|
|
"repository, use 'file://%s'", url, url);
|
|
if (has_dos_drive_prefix(url))
|
|
die("'%s' is not a URL; if you meant a local "
|
|
"repository, use 'file:///%s'", url, url);
|
|
die("'%s' is not a URL; if you meant a local repository, "
|
|
"use a 'file://' URL with an absolute path", url);
|
|
}
|
|
if (!url_parse(url, info))
|
|
die("invalid git URL '%s': %s", url, info->err);
|
|
}
|
|
|
|
static enum url_component get_component_or_die(const char *arg)
|
|
{
|
|
if (!strcmp("path", arg))
|
|
return URL_PATH;
|
|
if (!strcmp("host", arg))
|
|
return URL_HOST;
|
|
if (!strcmp("scheme", arg))
|
|
return URL_SCHEME;
|
|
if (!strcmp("user", arg))
|
|
return URL_USER;
|
|
if (!strcmp("password", arg))
|
|
return URL_PASSWORD;
|
|
if (!strcmp("port", arg))
|
|
return URL_PORT;
|
|
die("invalid git URL component '%s'", arg);
|
|
}
|
|
|
|
static char *extract_component(enum url_component component,
|
|
struct url_info *info)
|
|
{
|
|
size_t offset, length;
|
|
|
|
switch (component) {
|
|
case URL_SCHEME:
|
|
offset = 0;
|
|
length = info->scheme_len;
|
|
break;
|
|
case URL_USER:
|
|
offset = info->user_off;
|
|
length = info->user_len;
|
|
break;
|
|
case URL_PASSWORD:
|
|
offset = info->passwd_off;
|
|
length = info->passwd_len;
|
|
break;
|
|
case URL_HOST:
|
|
offset = info->host_off;
|
|
length = info->host_len;
|
|
break;
|
|
case URL_PORT:
|
|
offset = info->port_off;
|
|
length = info->port_len;
|
|
break;
|
|
case URL_PATH:
|
|
offset = info->path_off;
|
|
length = info->path_len;
|
|
break;
|
|
case URL_NONE:
|
|
return NULL;
|
|
}
|
|
|
|
return xstrndup(info->url + offset, length);
|
|
}
|
|
|
|
int cmd_url_parse(int argc,
|
|
const char **argv,
|
|
const char *prefix,
|
|
struct repository *repo UNUSED)
|
|
{
|
|
struct url_info info;
|
|
enum url_component selected = URL_NONE;
|
|
char *extracted;
|
|
int i;
|
|
|
|
argc = parse_options(argc, argv, prefix, builtin_url_parse_options,
|
|
builtin_url_parse_usage, 0);
|
|
|
|
if (argc == 0)
|
|
usage_with_options(builtin_url_parse_usage,
|
|
builtin_url_parse_options);
|
|
|
|
if (component_arg)
|
|
selected = get_component_or_die(component_arg);
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
parse_or_die(argv[i], &info);
|
|
|
|
if (selected != URL_NONE) {
|
|
extracted = extract_component(selected, &info);
|
|
if (extracted) {
|
|
puts(extracted);
|
|
free(extracted);
|
|
}
|
|
}
|
|
|
|
free(info.url);
|
|
}
|
|
|
|
return 0;
|
|
}
|