[PATCH 1/2] Add push by "export"

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



---
 Documentation/git-remote-helpers.txt |   33 ++++++++++++++++++
 transport-helper.c                   |   62 ++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+), 0 deletions(-)

diff --git a/Documentation/git-remote-helpers.txt b/Documentation/git-remote-helpers.txt
index 9a3c5bc..dede2e5 100644
--- a/Documentation/git-remote-helpers.txt
+++ b/Documentation/git-remote-helpers.txt
@@ -50,6 +50,17 @@ Supported if the helper has the "fetch" capability.
 +
 Supported if the helper has the "import" capability.
 
+'export' <sha1> [<name>]::
+	Exports the given commit to the given refname. The commit and
+	name (or lack of name) must be suitable for exporting,
+	according to the flags that the helper has reported. Produces
+	a fast-import stream reimporting the exported commits to the
+	imported version of the branch, so that the git view of the
+	history matches what any other import of the history would
+	give.
++
+Supported if the helper has the "export" capability.
+
 If a fatal error occurs, the program writes the error message to
 stderr and exits. The caller should expect that a suitable error
 message has been printed if the child closes the connection without
@@ -75,6 +86,10 @@ CAPABILITIES
 	and --export-marks option to git-fast-import for more details)
 	located at the given filename.
 
+'export' [flags]::
+	This helper supports the 'export' command. The flags specify
+	features of the history that may be exported (see below).
+
 REF LIST ATTRIBUTES
 -------------------
 
@@ -82,6 +97,24 @@ REF LIST ATTRIBUTES
 	This ref is unchanged since the last import or fetch, although
 	the helper cannot necessarily determine what value that produced.
 
+EXPORT FLAGS
+------------
+
+Regardless of flags, an exported commit may only have parents which
+have either been exported previously in this session or which were
+produced by fast-import.
+
+'anonymous'::
+	A commit may be exported without it being immediately written
+	to some particular name. This is required in order to use the
+	export command without a name.
+
+'merges'::
+	A commit may have multiple parents.
+
+'branches'::
+	A commit may be exported to a name which did not previously exist.
+
 Documentation
 -------------
 Documentation by Daniel Barkalow.
diff --git a/transport-helper.c b/transport-helper.c
index cc8707f..2b1450e 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -14,6 +14,7 @@ struct helper_data
 	char *marks_filename;
 	unsigned fetch : 1;
 	unsigned import : 1;
+	unsigned export : 1;
 };
 
 static struct child_process *get_helper(struct transport *transport)
@@ -52,6 +53,8 @@ static struct child_process *get_helper(struct transport *transport)
 			data->fetch = 1;
 		if (!strcmp(buf.buf, "import"))
 			data->import = 1;
+		if (!strcmp(buf.buf, "export"))
+			data->export = 1;
 		if (!prefixcmp(buf.buf, "marks "))
 			data->marks_filename = xstrdup(buf.buf + 6);
 	}
@@ -175,6 +178,64 @@ static int fetch(struct transport *transport,
 	return -1;
 }
 
+static int push_with_export(struct transport *transport, struct ref *remote_refs, int flags) {
+	struct child_process fastimport;
+	struct child_process *helper = get_helper(transport);
+	struct ref *ref, *has;
+	struct rev_info revs;
+	struct commit *commit;
+
+	if (get_importer(transport, &fastimport))
+		die("Couldn't run fast-import");
+
+	for (ref = remote_refs; ref; ref = ref->next) {
+		if (!ref->peer_ref) {
+			ref->status = REF_STATUS_NONE;
+			continue;
+		}
+		init_revisions(&revs, NULL);
+		revs.reverse = 1;
+		for (has = remote_refs; has; has = has->next) {
+			commit = lookup_commit(has->old_sha1);
+			commit->object.flags |= UNINTERESTING;
+			add_pending_object(&revs, &commit->object, has->name);
+		}
+		commit = lookup_commit(ref->peer_ref->new_sha1);
+		add_pending_object(&revs, &commit->object, ref->name);
+
+		if (prepare_revision_walk(&revs))
+			die("Something wrong");
+
+		ref->status = REF_STATUS_UPTODATE;
+		while ((commit = get_revision(&revs))) {
+			ref->status = REF_STATUS_EXPECTING_REPORT;
+			write_in_full(helper->in, "export ", 7);
+			write_in_full(helper->in, sha1_to_hex(commit->object.sha1), 40);
+			write_in_full(helper->in, " ", 1);
+			write_in_full(helper->in, ref->name, strlen(ref->name));
+			write_in_full(helper->in, "\n", 1);
+		}
+	}
+	disconnect_helper(transport);
+	finish_command(&fastimport);
+
+	for (ref = remote_refs; ref; ref = ref->next) {
+		read_ref(ref->name, ref->new_sha1);
+		if (ref->status == REF_STATUS_EXPECTING_REPORT)
+			ref->status = REF_STATUS_OK;
+	}
+
+	return 0;
+}
+
+static int push(struct transport *transport, struct ref *remote_refs, int flags) {
+	struct helper_data *data = transport->data;
+	if (data->export)
+		return push_with_export(transport, remote_refs, flags);
+
+	return -1;
+}
+
 static struct ref *get_refs_list(struct transport *transport, int for_push)
 {
 	struct child_process *helper;
@@ -241,6 +302,7 @@ int transport_helper_init(struct transport *transport)
 	transport->data = data;
 	transport->get_refs_list = get_refs_list;
 	transport->fetch = fetch;
+	transport->push_refs = push;
 	transport->disconnect = disconnect_helper;
 	return 0;
 }
-- 
1.6.4.rc3.27.g95032.dirty

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]