@matheusbsbs / matheus-bagliano / commits / 25d5cc488a
Fork 0

Pass unknown protocols to external protocol handlers

Change URL handling to allow external protocol handlers to implement new protocols without the '::' syntax if helper name does not conflict with any built-in protocol. foo:// now invokes git-remote-foo with foo:// as the URL. Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Ilari Liusvaara committed Dec 9, 2009 at 17:26 UTC 25d5cc488a75cc232e97af42759812d9aa398713
2 files changed +72 -16
transport-helper.c
+11 -1
@@ -63,6 +63,16 @@ static void write_constant(int fd, const char *str)
63 die_errno("Full write to remote helper failed");
64 }
65
66 +const char *remove_ext_force(const char *url)
67 +{
68 + if (url) {
69 + const char *colon = strchr(url, ':');
70 + if (colon && colon[1] == ':')
71 + return colon + 2;
72 + }
73 + return url;
74 +}
75 +
76 static struct child_process *get_helper(struct transport *transport)
77 {
78 struct helper_data *data = transport->data;
@@ -83,7 +93,7 @@ static struct child_process *get_helper(struct transport *transport)
93 strbuf_addf(&buf, "remote-%s", data->name);
94 helper->argv[0] = strbuf_detach(&buf, NULL);
95 helper->argv[1] = transport->remote->name;
86 - helper->argv[2] = transport->url;
96 + helper->argv[2] = remove_ext_force(transport->url);
97 helper->git_cmd = 1;
98 if (start_command(helper))
99 die("Unable to run helper: git %s", helper->argv[0]);
transport.c
+61 -15
@@ -780,6 +780,44 @@ static int is_file(const char *url)
780 return S_ISREG(buf.st_mode);
781 }
782
783 +static int is_url(const char *url)
784 +{
785 + const char *url2, *first_slash;
786 +
787 + if (!url)
788 + return 0;
789 + url2 = url;
790 + first_slash = strchr(url, '/');
791 +
792 + /* Input with no slash at all or slash first can't be URL. */
793 + if (!first_slash || first_slash == url)
794 + return 0;
795 + /* Character before must be : and next must be /. */
796 + if (first_slash[-1] != ':' || first_slash[1] != '/')
797 + return 0;
798 + /* There must be something before the :// */
799 + if (first_slash == url + 1)
800 + return 0;
801 + /*
802 + * Check all characters up to first slash - 1. Only alphanum
803 + * is allowed.
804 + */
805 + url2 = url;
806 + while (url2 < first_slash - 1) {
807 + if (!isalnum((unsigned char)*url2))
808 + return 0;
809 + url2++;
810 + }
811 +
812 + /* Valid enough. */
813 + return 1;
814 +}
815 +
816 +static int external_specification_len(const char *url)
817 +{
818 + return strchr(url, ':') - url;
819 +}
820 +
821 struct transport *transport_get(struct remote *remote, const char *url)
822 {
823 struct transport *ret = xcalloc(1, sizeof(*ret));
@@ -805,30 +843,23 @@ struct transport *transport_get(struct remote *remote, const char *url)
843
844 if (remote && remote->foreign_vcs) {
845 transport_helper_init(ret, remote->foreign_vcs);
808 - return ret;
809 - }
810 -
811 - if (!prefixcmp(url, "rsync:")) {
846 + } else if (!prefixcmp(url, "rsync:")) {
847 ret->get_refs_list = get_refs_via_rsync;
848 ret->fetch = fetch_objs_via_rsync;
849 ret->push = rsync_transport_push;
815 -
816 - } else if (!prefixcmp(url, "http://")
817 - || !prefixcmp(url, "https://")
818 - || !prefixcmp(url, "ftp://")) {
819 - transport_helper_init(ret, "curl");
820 -#ifdef NO_CURL
821 - error("git was compiled without libcurl support.");
822 -#endif
823 -
850 } else if (is_local(url) && is_file(url)) {
851 struct bundle_transport_data *data = xcalloc(1, sizeof(*data));
852 ret->data = data;
853 ret->get_refs_list = get_refs_from_bundle;
854 ret->fetch = fetch_refs_from_bundle;
855 ret->disconnect = close_bundle;
830 -
831 - } else {
856 + } else if (!is_url(url)
857 + || !prefixcmp(url, "file://")
858 + || !prefixcmp(url, "git://")
859 + || !prefixcmp(url, "ssh://")
860 + || !prefixcmp(url, "git+ssh://")
861 + || !prefixcmp(url, "ssh+git://")) {
862 + /* These are builtin smart transports. */
863 struct git_transport_data *data = xcalloc(1, sizeof(*data));
864 ret->data = data;
865 ret->set_option = set_git_option;
@@ -845,6 +876,21 @@ struct transport *transport_get(struct remote *remote, const char *url)
876 data->receivepack = "git-receive-pack";
877 if (remote->receivepack)
878 data->receivepack = remote->receivepack;
879 + } else if (!prefixcmp(url, "http://")
880 + || !prefixcmp(url, "https://")
881 + || !prefixcmp(url, "ftp://")) {
882 + /* These three are just plain special. */
883 + transport_helper_init(ret, "curl");
884 +#ifdef NO_CURL
885 + error("git was compiled without libcurl support.");
886 +#endif
887 + } else {
888 + /* Unknown protocol in URL. Pass to external handler. */
889 + int len = external_specification_len(url);
890 + char *handler = xmalloc(len + 1);
891 + handler[len] = 0;
892 + strncpy(handler, url, len);
893 + transport_helper_init(ret, handler);
894 }
895
896 return ret;