blob: 7e705538c04d3dbd1a1d2e1c8b8823bb377e76e6 [file]
#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;
}