{"thread":{"id":"20242","subject":"[RFC 00/11] Foreign VCS helper program for CVS repositories","startedAt":"2009-07-27T01:04:08Z","lastAt":"2009-07-30T02:35:20Z","messageCount":30,"participants":["Johan Herland","Shawn O. Pearce","Daniel Barkalow","Junio C Hamano","Alex Riesen"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"118852","messageId":"1248656659-21415-1-git-send-email-johan@herland.net","threadId":"20242","inReplyTo":null,"subject":"[RFC 00/11] Foreign VCS helper program for CVS repositories","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T01:04:08Z","receivedAt":"2009-07-27T01:04:08Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"This series is a first draft towards implementing a foreign VCS helper\nprogram for CVS.\n\nIt is based on the 'db/foreign-scm' and 'jh/notes' topics in 'pu'. As such,\nthis patch series should apply cleanly to current 'pu'.\n\nThe first 4 patches supply the necessary parts of Daniel Barkalow's\nforeign-scm topic that has not yet been merged to 'pu' (i.e. everything\nremaining in Daniel's original patch series, except the p4-specific stuff).\n\nThe next 2 patches add some functionality to git fast-import, for\nfacilitating the import of 'notes' objects (this is a _much_ faster way to\ngenerate/import notes than invoking \"git notes edit -m MSG\" for each note).\n\nNext, there are 3 patches tweaking and expanding the git-vcs API (with\ncorresponding implementations in the foreign transport code) to adjust for\nthe CVS helper's needs.\n\nThe final 2 patches add the git-vcs-cvs helper program that implements the\nfetch/import of objects from a local or remote CVS repository, along with\nselftests for verifying its correctness in some simple cases. This is a\nfirst RFC/draft of this helper program, and will hopefully grow along with\nthe foreign-scm feature itself until it provides a compelling alternative\nto \"git cvsimport\" and \"git cvsexportcommit\".\n\n\nDaniel Barkalow (4):\n  Add specification of git-vcs-* helper programs\n  Use a function to determine whether a remote is valid\n  Allow programs to not depend on remotes having urls\n  Add a transport implementation using git-vcs-* helpers\n\nJohan Herland (7):\n  Refactor path name parsing into new function: get_path_str()\n  Add support for mark references as path names\n  Preliminary clarifications to git-vcs documentation\n  Teach foreign transport code to perform the \"capabilities\" command\n  Introduce a 'marks <filename>' feature to the foreign transport code\n  First draft of CVS importer using the foreign-scm machinery\n  Add simple test cases of git-vcs-cvs functionality\n\n Documentation/git-fast-import.txt |    9 +-\n Documentation/git-vcs-cvs.txt     |   85 ++++\n Documentation/git-vcs.txt         |   88 ++++\n Makefile                          |   47 ++\n builtin-fetch.c                   |   19 +-\n builtin-ls-remote.c               |    4 +-\n builtin-push.c                    |   54 ++-\n configure.ac                      |    3 +\n fast-import.c                     |   71 ++--\n git-vcs-cvs.py                    |  697 +++++++++++++++++++++++++++++\n git_vcs_cvs/.gitignore            |    2 +\n git_vcs_cvs/Makefile              |   27 ++\n git_vcs_cvs/changeset.py          |  114 +++++\n git_vcs_cvs/commit_states.py      |   52 +++\n git_vcs_cvs/cvs.py                |  884 +++++++++++++++++++++++++++++++++++++\n git_vcs_cvs/cvs_revision_map.py   |  367 +++++++++++++++\n git_vcs_cvs/cvs_symbol_cache.py   |  283 ++++++++++++\n git_vcs_cvs/git.py                |  588 ++++++++++++++++++++++++\n git_vcs_cvs/setup.py              |   12 +\n git_vcs_cvs/util.py               |  147 ++++++\n remote.c                          |   13 +-\n t/t9800-foreign-vcs-cvs-basic.sh  |  518 ++++++++++++++++++++++\n t/t9801-foreign-vcs-cvs-fetch.sh  |  291 ++++++++++++\n t/test-lib.sh                     |    1 +\n transport-foreign.c               |  271 ++++++++++++\n transport.c                       |    4 +\n transport.h                       |    1 +\n 27 files changed, 4588 insertions(+), 64 deletions(-)\n create mode 100644 Documentation/git-vcs-cvs.txt\n create mode 100644 Documentation/git-vcs.txt\n create mode 100755 git-vcs-cvs.py\n create mode 100644 git_vcs_cvs/.gitignore\n create mode 100644 git_vcs_cvs/Makefile\n create mode 100644 git_vcs_cvs/__init__.py\n create mode 100644 git_vcs_cvs/changeset.py\n create mode 100644 git_vcs_cvs/commit_states.py\n create mode 100644 git_vcs_cvs/cvs.py\n create mode 100644 git_vcs_cvs/cvs_revision_map.py\n create mode 100644 git_vcs_cvs/cvs_symbol_cache.py\n create mode 100644 git_vcs_cvs/git.py\n create mode 100644 git_vcs_cvs/setup.py\n create mode 100644 git_vcs_cvs/util.py\n create mode 100755 t/t9800-foreign-vcs-cvs-basic.sh\n create mode 100755 t/t9801-foreign-vcs-cvs-fetch.sh\n create mode 100644 transport-foreign.c\n\n\nHave fun! :)\n\n...Johan\n"},{"id":"118853","messageId":"1248656659-21415-2-git-send-email-johan@herland.net","threadId":"20242","inReplyTo":"1248656659-21415-1-git-send-email-johan@herland.net","subject":"[RFC 01/11] Add specification of git-vcs-* helper programs","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T01:04:09Z","receivedAt":"2009-07-27T01:04:09Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"From: Daniel Barkalow <barkalow@iabervon.org>\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n Documentation/git-vcs.txt |   77 +++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 77 insertions(+), 0 deletions(-)\n create mode 100644 Documentation/git-vcs.txt\n\ndiff --git a/Documentation/git-vcs.txt b/Documentation/git-vcs.txt\nnew file mode 100644\nindex 0000000..402c927\n--- /dev/null\n+++ b/Documentation/git-vcs.txt\n@@ -0,0 +1,77 @@\n+git-vcs(1)\n+============\n+\n+NAME\n+----\n+git-vcs - Helper programs for interoperation with foreign systems\n+\n+SYNOPSIS\n+--------\n+'git vcs-<system>' <remote>\n+\n+DESCRIPTION\n+-----------\n+\n+These programs are normally not used directly by end users, but are\n+invoked by various git programs that interact with remote repositories\n+when the repository they would operate on uses a foreign system.\n+\n+Each 'git vcs-<system>' is a helper for interoperating with a\n+particular version control system. Different helpers have different\n+capabilities (limited both by the particular helper and by the\n+capabilities of the system they connect to), and they report what\n+capabilities they support.\n+\n+These programs can store refs in refs/<system>/*, and arbitrary\n+information in info/<system>.\n+\n+COMMANDS\n+--------\n+\n+Commands are given by the caller on the helper's standard input, one per line.\n+\n+'capabilities'::\n+\tOutputs a single line with a list of feature names separated\n+\tby spaces. Each of these indicates a supported feature of the\n+\thelper, and the caller will only attempt operations that are\n+\tsupported.\n+\n+'list'::\n+\tOutputs the names of refs, one per line. These may be\n+\tfollowed, after a single space, by \"changed\" or \"unchanged\",\n+\tindicating whether the foreign repository has changed from the\n+\tstate in the ref. If the helper doesn't know, it doesn't have\n+\tto provide a value. (In particular, it shouldn't do expensive\n+\toperations, such as importing the content, to see whether it\n+\tmatches.) Other information, not yet supported, may be output\n+\tas well, separated by single spaces.\n+\n+'import' ref::\n+\tImports the given ref by outputting it in git-fast-import\n+\tformat.\n+\n+'export' commit ref::\n+\tSends the given commit to the foreign system, with the\n+\tlocation given by ref, and reimports it by outputting it in\n+\tgit-fast-import format as the foreign system rendered it.\n++\n+All parents of commit must either have been created with 'import' or\n+have been passed to 'export' previously. Depending on the features,\n+there may be other restrictions on what may be exported.\n+\n+FEATURES\n+--------\n+\n+'export'::\n+\tHelper supports exporting commits, at least exporting\n+\tnon-merge commits whose parents are not the parents of any\n+\tother commit exported to the same branch or make in the other\n+\tsystem on the same branch.\n+\n+'export-branch'::\n+\tHelper supports creating new branches by exporting commits to\n+\tthem.\n+\n+'export-merges'::\n+\tHelper supports exporting two-parent merges, where both\n+\tparents have already been exported successfully.\n-- \n1.6.4.rc3.138.ga6b98.dirty\n"},{"id":"118855","messageId":"1248656659-21415-3-git-send-email-johan@herland.net","threadId":"20242","inReplyTo":"1248656659-21415-1-git-send-email-johan@herland.net","subject":"[RFC 02/11] Use a function to determine whether a remote is valid","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T01:04:10Z","receivedAt":"2009-07-27T01:04:10Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"From: Daniel Barkalow <barkalow@iabervon.org>\n\nCurrently, it only checks url, but it will allow other things in the future.\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n remote.c |   13 +++++++++----\n 1 files changed, 9 insertions(+), 4 deletions(-)\n\ndiff --git a/remote.c b/remote.c\nindex 6be9083..c5ac881 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -48,6 +48,11 @@ static int rewrite_nr;\n #define BUF_SIZE (2048)\n static char buffer[BUF_SIZE];\n \n+static int valid_remote(const struct remote *remote)\n+{\n+\treturn !!remote->url;\n+}\n+\n static const char *alias_url(const char *url)\n {\n \tint i, j;\n@@ -672,14 +677,14 @@ struct remote *remote_get(const char *name)\n \n \tret = make_remote(name, 0);\n \tif (valid_remote_nick(name)) {\n-\t\tif (!ret->url)\n+\t\tif (!valid_remote(ret))\n \t\t\tread_remotes_file(ret);\n-\t\tif (!ret->url)\n+\t\tif (!valid_remote(ret))\n \t\t\tread_branches_file(ret);\n \t}\n-\tif (name_given && !ret->url)\n+\tif (name_given && !valid_remote(ret))\n \t\tadd_url_alias(ret, name);\n-\tif (!ret->url)\n+\tif (!valid_remote(ret))\n \t\treturn NULL;\n \tret->fetch = parse_fetch_refspec(ret->fetch_refspec_nr, ret->fetch_refspec);\n \tret->push = parse_push_refspec(ret->push_refspec_nr, ret->push_refspec);\n-- \n1.6.4.rc3.138.ga6b98.dirty\n"},{"id":"118854","messageId":"1248656659-21415-4-git-send-email-johan@herland.net","threadId":"20242","inReplyTo":"1248656659-21415-1-git-send-email-johan@herland.net","subject":"[RFC 03/11] Allow programs to not depend on remotes having urls","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T01:04:11Z","receivedAt":"2009-07-27T01:04:11Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"From: Daniel Barkalow <barkalow@iabervon.org>\n\nFor fetch and ls-remote, which use the first url of a remote, have\ntransport_get() determine this by passing a remote and passing NULL\nfor the url. For push, which uses every url of a remote, use each url\nin turn if there are any, and use NULL if there are none.\n\nThis will allow the transport code to do something different if the\nlocation is not specified with a url.\n\nAlso, have the message for a fetch say \"foreign\" if there is no url.\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n builtin-fetch.c     |   19 +++++++++++------\n builtin-ls-remote.c |    4 +-\n builtin-push.c      |   54 +++++++++++++++++++++++++++++++++-----------------\n transport.c         |    3 ++\n 4 files changed, 52 insertions(+), 28 deletions(-)\n\ndiff --git a/builtin-fetch.c b/builtin-fetch.c\nindex 817dd6b..3f32db6 100644\n--- a/builtin-fetch.c\n+++ b/builtin-fetch.c\n@@ -346,12 +346,17 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,\n \t\t\twhat = rm->name;\n \t\t}\n \n-\t\turl_len = strlen(url);\n-\t\tfor (i = url_len - 1; url[i] == '/' && 0 <= i; i--)\n-\t\t\t;\n-\t\turl_len = i + 1;\n-\t\tif (4 < i && !strncmp(\".git\", url + i - 3, 4))\n-\t\t\turl_len = i - 3;\n+\t\tif (url) {\n+\t\t\turl_len = strlen(url);\n+\t\t\tfor (i = url_len - 1; url[i] == '/' && 0 <= i; i--)\n+\t\t\t\t;\n+\t\t\turl_len = i + 1;\n+\t\t\tif (4 < i && !strncmp(\".git\", url + i - 3, 4))\n+\t\t\t\turl_len = i - 3;\n+\t\t} else {\n+\t\t\turl = \"foriegn\";\n+\t\t\turl_len = strlen(url);\n+\t\t}\n \n \t\tnote_len = 0;\n \t\tif (*what) {\n@@ -663,7 +668,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)\n \tif (!remote)\n \t\tdie(\"Where do you want to fetch from today?\");\n \n-\ttransport = transport_get(remote, remote->url[0]);\n+\ttransport = transport_get(remote, NULL);\n \tif (verbosity >= 2)\n \t\ttransport->verbose = 1;\n \tif (verbosity < 0)\ndiff --git a/builtin-ls-remote.c b/builtin-ls-remote.c\nindex 78a88f7..4c6fc58 100644\n--- a/builtin-ls-remote.c\n+++ b/builtin-ls-remote.c\n@@ -87,9 +87,9 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n \t\t}\n \t}\n \tremote = nongit ? NULL : remote_get(dest);\n-\tif (remote && !remote->url_nr)\n+\tif (!nongit && !remote)\n \t\tdie(\"remote %s has no configured URL\", dest);\n-\ttransport = transport_get(remote, remote ? remote->url[0] : dest);\n+\ttransport = transport_get(remote, remote ? NULL : dest);\n \tif (uploadpack != NULL)\n \t\ttransport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);\n \ndiff --git a/builtin-push.c b/builtin-push.c\nindex 1d92e22..ae63521 100644\n--- a/builtin-push.c\n+++ b/builtin-push.c\n@@ -88,6 +88,26 @@ static void setup_default_push_refspecs(void)\n \t}\n }\n \n+static int push_with_options(struct transport *transport, int flags)\n+{\n+\tint err;\n+\tif (receivepack)\n+\t\ttransport_set_option(transport,\n+\t\t\t\t     TRANS_OPT_RECEIVEPACK, receivepack);\n+\tif (thin)\n+\t\ttransport_set_option(transport, TRANS_OPT_THIN, \"yes\");\n+\n+\tif (flags & TRANSPORT_PUSH_VERBOSE)\n+\t\tfprintf(stderr, \"Pushing to %s\\n\", transport->url);\n+\terr = transport_push(transport, refspec_nr, refspec, flags);\n+\terr |= transport_disconnect(transport);\n+\n+\tif (!err)\n+\t\treturn 0;\n+\n+\treturn 1;\n+}\n+\n static int do_push(const char *repo, int flags)\n {\n \tint i, errs;\n@@ -136,26 +156,22 @@ static int do_push(const char *repo, int flags)\n \t\turl = remote->url;\n \t\turl_nr = remote->url_nr;\n \t}\n-\tfor (i = 0; i < url_nr; i++) {\n+\tif (url_nr) {\n+\t\tfor (i = 0; i < url_nr; i++) {\n+\t\t\tstruct transport *transport =\n+\t\t\t\ttransport_get(remote, url[i]);\n+\t\t\tif (push_with_options(transport, flags)) {\n+\t\t\t\terror(\"failed to push some refs to '%s'\", url[i]);\n+\t\t\t\terrs++;\n+\t\t\t}\n+\t\t}\n+\t} else {\n \t\tstruct transport *transport =\n-\t\t\ttransport_get(remote, url[i]);\n-\t\tint err;\n-\t\tif (receivepack)\n-\t\t\ttransport_set_option(transport,\n-\t\t\t\t\t     TRANS_OPT_RECEIVEPACK, receivepack);\n-\t\tif (thin)\n-\t\t\ttransport_set_option(transport, TRANS_OPT_THIN, \"yes\");\n-\n-\t\tif (flags & TRANSPORT_PUSH_VERBOSE)\n-\t\t\tfprintf(stderr, \"Pushing to %s\\n\", url[i]);\n-\t\terr = transport_push(transport, refspec_nr, refspec, flags);\n-\t\terr |= transport_disconnect(transport);\n-\n-\t\tif (!err)\n-\t\t\tcontinue;\n-\n-\t\terror(\"failed to push some refs to '%s'\", url[i]);\n-\t\terrs++;\n+\t\t\ttransport_get(remote, NULL);\n+\t\tif (push_with_options(transport, flags)) {\n+\t\t\terror(\"failed to push some refs to foreign system\");\n+\t\t\terrs++;\n+\t\t}\n \t}\n \treturn !!errs;\n }\ndiff --git a/transport.c b/transport.c\nindex 13fbca4..2864f40 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -793,6 +793,9 @@ struct transport *transport_get(struct remote *remote, const char *url)\n \tstruct transport *ret = xcalloc(1, sizeof(*ret));\n \n \tret->remote = remote;\n+\n+\tif (!url && remote && remote->url)\n+\t\turl = remote->url[0];\n \tret->url = url;\n \n \tif (remote && remote->foreign_vcs) {\n-- \n1.6.4.rc3.138.ga6b98.dirty\n"},{"id":"118856","messageId":"1248656659-21415-5-git-send-email-johan@herland.net","threadId":"20242","inReplyTo":"1248656659-21415-1-git-send-email-johan@herland.net","subject":"[RFC 04/11] Add a transport implementation using git-vcs-* helpers","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T01:04:12Z","receivedAt":"2009-07-27T01:04:12Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"From: Daniel Barkalow <barkalow@iabervon.org>\n\nThis is somewhat careless about pushes (that is, it attempts to make\npushes that the helper can't necessarily handle), but actually works for\nfetches and simple pushes.\n\nSigned-off-by: Daniel Barkalow <barkalow@iabervon.org>\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n Makefile            |    1 +\n remote.c            |    2 +-\n transport-foreign.c |  200 +++++++++++++++++++++++++++++++++++++++++++++++++++\n transport.c         |    1 +\n transport.h         |    1 +\n 5 files changed, 204 insertions(+), 1 deletions(-)\n create mode 100644 transport-foreign.c\n\ndiff --git a/Makefile b/Makefile\nindex f396e52..6b39d56 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -554,6 +554,7 @@ LIB_OBJS += symlinks.o\n LIB_OBJS += tag.o\n LIB_OBJS += trace.o\n LIB_OBJS += transport.o\n+LIB_OBJS += transport-foreign.o\n LIB_OBJS += transport-shim.o\n LIB_OBJS += tree-diff.o\n LIB_OBJS += tree.o\ndiff --git a/remote.c b/remote.c\nindex c5ac881..8d1560e 100644\n--- a/remote.c\n+++ b/remote.c\n@@ -50,7 +50,7 @@ static char buffer[BUF_SIZE];\n \n static int valid_remote(const struct remote *remote)\n {\n-\treturn !!remote->url;\n+\treturn remote->url || remote->foreign_vcs;\n }\n \n static const char *alias_url(const char *url)\ndiff --git a/transport-foreign.c b/transport-foreign.c\nnew file mode 100644\nindex 0000000..29aad77\n--- /dev/null\n+++ b/transport-foreign.c\n@@ -0,0 +1,200 @@\n+#include \"cache.h\"\n+#include \"transport.h\"\n+\n+#include \"run-command.h\"\n+#include \"commit.h\"\n+#include \"diff.h\"\n+#include \"revision.h\"\n+\n+struct foreign_data\n+{\n+\tstruct child_process *importer;\n+};\n+\n+static struct child_process *get_importer(struct transport *transport)\n+{\n+\tstruct child_process *importer = transport->data;\n+\tif (!importer) {\n+\t\tstruct strbuf buf;\n+\t\timporter = xcalloc(1, sizeof(*importer));\n+\t\timporter->in = -1;\n+\t\timporter->out = -1;\n+\t\timporter->err = 0;\n+\t\timporter->argv = xcalloc(3, sizeof(*importer->argv));\n+\t\tstrbuf_init(&buf, 80);\n+\t\tstrbuf_addf(&buf, \"vcs-%s\", transport->remote->foreign_vcs);\n+\t\timporter->argv[0] = buf.buf;\n+\t\timporter->argv[1] = transport->remote->name;\n+\t\timporter->git_cmd = 1;\n+\t\tstart_command(importer);\n+\t\ttransport->data = importer;\n+\t}\n+\treturn importer;\n+}\n+\n+static int disconnect_foreign(struct transport *transport)\n+{\n+\tstruct child_process *importer = transport->data;\n+\tif (importer) {\n+\t\twrite(importer->in, \"\\n\", 1);\n+\t\tclose(importer->in);\n+\t\tfinish_command(importer);\n+\t\tfree(importer);\n+\t\ttransport->data = NULL;\n+\t}\n+\treturn 0;\n+}\n+\n+static int fetch_refs_via_foreign(struct transport *transport,\n+\t\t\t\t  int nr_heads, struct ref **to_fetch)\n+{\n+\tstruct child_process *importer;\n+\tstruct child_process fastimport;\n+\tstruct ref *posn;\n+\tint i, count;\n+\n+\tcount = 0;\n+\tfor (i = 0; i < nr_heads; i++) {\n+\t\tposn = to_fetch[i];\n+\t\tif (posn->status & REF_STATUS_UPTODATE)\n+\t\t\tcontinue;\n+\t\tcount++;\n+\t}\n+\tif (count) {\n+\t\timporter = get_importer(transport);\n+\n+\t\tmemset(&fastimport, 0, sizeof(fastimport));\n+\t\tfastimport.in = importer->out;\n+\t\tfastimport.argv = xcalloc(3, sizeof(*fastimport.argv));\n+\t\tfastimport.argv[0] = \"fast-import\";\n+\t\tfastimport.argv[1] = \"--quiet\";\n+\t\tfastimport.git_cmd = 1;\n+\t\tstart_command(&fastimport);\n+\n+\t\tfor (i = 0; i < nr_heads; i++) {\n+\t\t\tposn = to_fetch[i];\n+\t\t\tif (posn->status & REF_STATUS_UPTODATE)\n+\t\t\t\tcontinue;\n+\t\t\twrite(importer->in, \"import \", 7);\n+\t\t\twrite(importer->in, posn->name, strlen(posn->name));\n+\t\t\twrite(importer->in, \"\\n\", 1);\n+\t\t}\n+\t\tdisconnect_foreign(transport);\n+\t\tfinish_command(&fastimport);\n+\t}\n+\tfor (i = 0; i < nr_heads; i++) {\n+\t\tposn = to_fetch[i];\n+\t\tif (posn->status & REF_STATUS_UPTODATE)\n+\t\t\tcontinue;\n+\t\tread_ref(posn->name, posn->old_sha1);\n+\t}\n+\treturn 0;\n+}\n+\n+static struct ref *get_refs_via_foreign(struct transport *transport, int for_push)\n+{\n+\tstruct child_process *importer;\n+\tstruct ref *ret = NULL;\n+\tstruct ref **end = &ret;\n+\tstruct strbuf buf;\n+\tFILE *file;\n+\n+\timporter = get_importer(transport);\n+\twrite(importer->in, \"list\\n\", 5);\n+\n+\tstrbuf_init(&buf, 0);\n+\tfile = fdopen(importer->out, \"r\");\n+\twhile (1) {\n+\t\tchar *eon;\n+\t\tif (strbuf_getline(&buf, file, '\\n') == EOF)\n+\t\t\tbreak;\n+\n+\t\tif (!*buf.buf)\n+\t\t\tbreak;\n+\n+\t\teon = strchr(buf.buf, ' ');\n+\t\tif (eon)\n+\t\t\t*eon = '\\0';\n+\t\t*end = alloc_ref(buf.buf);\n+\t\tif (eon) {\n+\t\t\tif (strstr(eon + 1, \"unchanged\")) {\n+\t\t\t\t(*end)->status |= REF_STATUS_UPTODATE;\n+\t\t\t\tif (read_ref((*end)->name, (*end)->old_sha1))\n+\t\t\t\t\tdie(\"Unchanged?\");\n+\t\t\t\tfprintf(stderr, \"Old: %p %s\\n\", *end, sha1_to_hex((*end)->old_sha1));\n+\t\t\t}\n+\t\t}\n+\t\tend = &((*end)->next);\n+\t\tstrbuf_reset(&buf);\n+\t}\n+\n+\tstrbuf_release(&buf);\n+\treturn ret;\n+}\n+\n+static int foreign_push(struct transport *transport, struct ref *remote_refs, int flags) {\n+\tstruct ref *ref, *has;\n+\tstruct child_process *importer;\n+\tstruct rev_info revs;\n+\tstruct commit *commit;\n+\tstruct child_process fastimport;\n+\n+\timporter = get_importer(transport);\n+\n+\tmemset(&fastimport, 0, sizeof(fastimport));\n+\tfastimport.in = importer->out;\n+\tfastimport.argv = xcalloc(3, sizeof(*fastimport.argv));\n+\tfastimport.argv[0] = \"fast-import\";\n+\tfastimport.argv[1] = \"--quiet\";\n+\tfastimport.git_cmd = 1;\n+\tstart_command(&fastimport);\n+\tfor (ref = remote_refs; ref; ref = ref->next) {\n+\t\tif (!ref->peer_ref) {\n+\t\t\tref->status = REF_STATUS_NONE;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tinit_revisions(&revs, NULL);\n+\t\trevs.reverse = 1;\n+\t\tfor (has = remote_refs; has; has = has->next) {\n+\t\t\tcommit = lookup_commit(has->old_sha1);\n+\t\t\tcommit->object.flags |= UNINTERESTING;\n+\t\t\tadd_pending_object(&revs, &commit->object, has->name);\n+\t\t}\n+\t\tcommit = lookup_commit(ref->peer_ref->new_sha1);\n+\t\tadd_pending_object(&revs, &commit->object, ref->name);\n+\n+\t\tif (prepare_revision_walk(&revs))\n+\t\t\tdie(\"Something wrong\");\n+\n+\t\tref->status = REF_STATUS_UPTODATE;\n+\t\twhile ((commit = get_revision(&revs))) {\n+\t\t\tref->status = REF_STATUS_EXPECTING_REPORT;\n+\t\t\tfprintf(stderr, \"export %s %s\\n\", sha1_to_hex(commit->object.sha1), ref->name);\n+\t\t\twrite(importer->in, \"export \", 7);\n+\t\t\twrite(importer->in, sha1_to_hex(commit->object.sha1), 40);\n+\t\t\twrite(importer->in, \" \", 1);\n+\t\t\twrite(importer->in, ref->name, strlen(ref->name));\n+\t\t\twrite(importer->in, \"\\n\", 1);\n+\t\t}\n+\t}\n+\n+\tdisconnect_foreign(transport);\n+\tfinish_command(&fastimport);\n+\n+\tfor (ref = remote_refs; ref; ref = ref->next) {\n+\t\tread_ref(ref->name, ref->new_sha1);\n+\t\tif (ref->status == REF_STATUS_EXPECTING_REPORT)\n+\t\t\tref->status = REF_STATUS_OK;\n+\t}\n+\n+\treturn 0;\n+}\n+\n+void transport_foreign_init(struct transport *transport)\n+{\n+\ttransport->get_refs_list = get_refs_via_foreign;\n+\ttransport->fetch = fetch_refs_via_foreign;\n+\ttransport->push_refs = foreign_push;\n+\ttransport->disconnect = disconnect_foreign;\n+\ttransport->url = transport->remote->foreign_vcs;\n+}\ndiff --git a/transport.c b/transport.c\nindex 2864f40..4e984ca 100644\n--- a/transport.c\n+++ b/transport.c\n@@ -799,6 +799,7 @@ struct transport *transport_get(struct remote *remote, const char *url)\n \tret->url = url;\n \n \tif (remote && remote->foreign_vcs) {\n+\t\ttransport_foreign_init(ret);\n \t} else if (!prefixcmp(url, \"rsync:\")) {\n \t\tret->get_refs_list = get_refs_via_rsync;\n \t\tret->fetch = fetch_objs_via_rsync;\ndiff --git a/transport.h b/transport.h\nindex 229a7b4..2e1bd6c 100644\n--- a/transport.h\n+++ b/transport.h\n@@ -116,6 +116,7 @@ int transport_disconnect(struct transport *transport);\n char *transport_anonymize_url(const char *url);\n \n /* Transport methods defined outside transport.c */\n+void transport_foreign_init(struct transport *transport);\n void transport_shim_init(struct transport *transport, const char *name);\n \n #endif\n-- \n1.6.4.rc3.138.ga6b98.dirty\n"},{"id":"118857","messageId":"1248656659-21415-6-git-send-email-johan@herland.net","threadId":"20242","inReplyTo":"1248656659-21415-1-git-send-email-johan@herland.net","subject":"[RFC 05/11] Refactor path name parsing into new function: get_path_str()","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T01:04:13Z","receivedAt":"2009-07-27T01:04:13Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"This is in preparation for adding mark reference capability to path names.\n\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n fast-import.c |   60 ++++++++++++++++++++++++++++++--------------------------\n 1 files changed, 32 insertions(+), 28 deletions(-)\n\ndiff --git a/fast-import.c b/fast-import.c\nindex 7ef9865..8a7cdc1 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -1853,6 +1853,24 @@ static void load_branch(struct branch *b)\n \t}\n }\n \n+static const char *get_path_str(\n+\tstruct strbuf *sb,\n+\tconst char *p,\n+\tchar endc,\n+\tconst char **endp)\n+{\n+\tstrbuf_reset(sb);\n+\t*endp = p;\n+\tif (!unquote_c_style(sb, p, endp)) {\n+\t\t/* successfully unquoted C-style quoted name */\n+\t\tp = sb->buf;\n+\t} else {\n+\t\t/* regular path ending at endc */\n+\t\t*endp = strchr(p, endc);\n+\t}\n+\treturn p;\n+}\n+\n static void file_change_m(struct branch *b)\n {\n \tconst char *p = command_buf.buf + 2;\n@@ -1896,12 +1914,9 @@ static void file_change_m(struct branch *b)\n \tif (*p++ != ' ')\n \t\tdie(\"Missing space after SHA1: %s\", command_buf.buf);\n \n-\tstrbuf_reset(&uq);\n-\tif (!unquote_c_style(&uq, p, &endp)) {\n-\t\tif (*endp)\n-\t\t\tdie(\"Garbage after path in: %s\", command_buf.buf);\n-\t\tp = uq.buf;\n-\t}\n+\tp = get_path_str(&uq, p, 0, &endp);\n+\tif (*endp)\n+\t\tdie(\"Garbage after path in: %s\", command_buf.buf);\n \n \tif (S_ISGITLINK(mode)) {\n \t\tif (inline_data)\n@@ -1948,12 +1963,9 @@ static void file_change_d(struct branch *b)\n \tstatic struct strbuf uq = STRBUF_INIT;\n \tconst char *endp;\n \n-\tstrbuf_reset(&uq);\n-\tif (!unquote_c_style(&uq, p, &endp)) {\n-\t\tif (*endp)\n-\t\t\tdie(\"Garbage after path in: %s\", command_buf.buf);\n-\t\tp = uq.buf;\n-\t}\n+\tp = get_path_str(&uq, p, 0, &endp);\n+\tif (*endp)\n+\t\tdie(\"Garbage after path in: %s\", command_buf.buf);\n \ttree_content_remove(&b->branch_tree, p, NULL);\n }\n \n@@ -1966,29 +1978,21 @@ static void file_change_cr(struct branch *b, int rename)\n \tstruct tree_entry leaf;\n \n \ts = command_buf.buf + 2;\n-\tstrbuf_reset(&s_uq);\n-\tif (!unquote_c_style(&s_uq, s, &endp)) {\n-\t\tif (*endp != ' ')\n-\t\t\tdie(\"Missing space after source: %s\", command_buf.buf);\n-\t} else {\n-\t\tendp = strchr(s, ' ');\n-\t\tif (!endp)\n-\t\t\tdie(\"Missing space after source: %s\", command_buf.buf);\n+\ts = get_path_str(&s_uq, s, ' ', &endp);\n+\tif (*endp != ' ')\n+\t\tdie(\"Missing space after source: %s\", command_buf.buf);\n+\tif (s != s_uq.buf) {\n \t\tstrbuf_add(&s_uq, s, endp - s);\n+\t\ts = s_uq.buf;\n \t}\n-\ts = s_uq.buf;\n \n \tendp++;\n \tif (!*endp)\n \t\tdie(\"Missing dest: %s\", command_buf.buf);\n \n-\td = endp;\n-\tstrbuf_reset(&d_uq);\n-\tif (!unquote_c_style(&d_uq, d, &endp)) {\n-\t\tif (*endp)\n-\t\t\tdie(\"Garbage after dest in: %s\", command_buf.buf);\n-\t\td = d_uq.buf;\n-\t}\n+\td = get_path_str(&d_uq, endp, 0, &endp);\n+\tif (*endp)\n+\t\tdie(\"Garbage after dest in: %s\", command_buf.buf);\n \n \tmemset(&leaf, 0, sizeof(leaf));\n \tif (rename)\n-- \n1.6.4.rc3.138.ga6b98.dirty\n"},{"id":"118858","messageId":"1248656659-21415-7-git-send-email-johan@herland.net","threadId":"20242","inReplyTo":"1248656659-21415-1-git-send-email-johan@herland.net","subject":"[RFC 06/11] Add support for mark references as path names","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T01:04:14Z","receivedAt":"2009-07-27T01:04:14Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"When using a mark reference as a path name, the mark reference will be\nexpanded to the 40-byte hex version of the object name associated with the\nmark. This is useful e.g. when importing notes objects (where the filenames\nin a notes tree are the object names of the annotated objects).\n\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n Documentation/git-fast-import.txt |    9 +++++++--\n fast-import.c                     |   11 +++++++++--\n 2 files changed, 16 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex c2f483a..bbc8b78 100644\n--- a/Documentation/git-fast-import.txt\n+++ b/Documentation/git-fast-import.txt\n@@ -487,12 +487,17 @@ in octal.  Git only supports the following modes:\n \n In both formats `<path>` is the complete path of the file to be added\n (if not already existing) or modified (if already existing).\n+`<path>` may also be a mark reference (`:<idnum>`) set by a prior\n+command, which will expand to a full 40-byte SHA-1 of the Git object\n+associated with the mark. This is useful e.g. when importing commit\n+notes (the filenames in a notes commit are the object names of the\n+annotated commits).\n \n A `<path>` string must use UNIX-style directory separators (forward\n slash `/`), may contain any byte other than `LF`, and must not\n-start with double quote (`\"`).\n+start with double quote (`\"`) or colon (`:`).\n \n-If an `LF` or double quote must be encoded into `<path>` shell-style\n+If an `LF`, double quote or colon must be encoded into `<path>` shell-style\n quoting should be used, e.g. `\"path/with\\n and \\\" in it\"`.\n \n The value of `<path>` must be in canonical form. That is it must not:\ndiff --git a/fast-import.c b/fast-import.c\nindex 8a7cdc1..3edfcf0 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -85,13 +85,13 @@ Format of STDIN stream:\n      # common escapes of 'c' (e..g \\n, \\t, \\\\, \\\") or \\nnn where nnn\n      # is the signed byte value in octal.  Note that the only\n      # characters which must actually be escaped to protect the\n-     # stream formatting is: \\, \" and LF.  Otherwise these values\n+     # stream formatting is: \\, \", : and LF.  Otherwise these values\n      # are UTF8.\n      #\n   ref_str     ::= ref;\n   sha1exp_str ::= sha1exp;\n   tag_str     ::= tag;\n-  path_str    ::= path    | '\"' quoted(path)    '\"' ;\n+  path_str    ::= path | '\"' quoted(path) '\"' | idnum;\n   mode        ::= '100644' | '644'\n                 | '100755' | '755'\n                 | '120000'\n@@ -1864,6 +1864,13 @@ static const char *get_path_str(\n \tif (!unquote_c_style(sb, p, endp)) {\n \t\t/* successfully unquoted C-style quoted name */\n \t\tp = sb->buf;\n+\t} else if (*p == ':') {\n+\t\t/* resolve mark reference */\n+\t\tchar *x;\n+\t\tstruct object_entry *pe = find_mark(strtoumax(p + 1, &x, 10));\n+\t\t*endp = x;\n+\t\tstrbuf_add(sb, sha1_to_hex(pe->sha1), 40);\n+\t\tp = sb->buf;\n \t} else {\n \t\t/* regular path ending at endc */\n \t\t*endp = strchr(p, endc);\n-- \n1.6.4.rc3.138.ga6b98.dirty\n"},{"id":"118859","messageId":"1248656659-21415-8-git-send-email-johan@herland.net","threadId":"20242","inReplyTo":"1248656659-21415-1-git-send-email-johan@herland.net","subject":"[RFC 07/11] Preliminary clarifications to git-vcs documentation","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T01:04:15Z","receivedAt":"2009-07-27T01:04:15Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"Signed-off-by: Johan Herland <johan@herland.net>\n---\n Documentation/git-vcs.txt |    7 +++++--\n 1 files changed, 5 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-vcs.txt b/Documentation/git-vcs.txt\nindex 402c927..febe415 100644\n--- a/Documentation/git-vcs.txt\n+++ b/Documentation/git-vcs.txt\n@@ -22,13 +22,15 @@ capabilities (limited both by the particular helper and by the\n capabilities of the system they connect to), and they report what\n capabilities they support.\n \n-These programs can store refs in refs/<system>/*, and arbitrary\n-information in info/<system>.\n+These programs can store refs in refs/<system>/*, note refs in\n+refs/notes/<system>/*, and arbitrary information in info/<system>/*.\n \n COMMANDS\n --------\n \n Commands are given by the caller on the helper's standard input, one per line.\n+The output of each command must be produced on the helper's standard output.\n+The helper's standard error stream can be used for status/progress messages.\n \n 'capabilities'::\n \tOutputs a single line with a list of feature names separated\n@@ -45,6 +47,7 @@ Commands are given by the caller on the helper's standard input, one per line.\n \toperations, such as importing the content, to see whether it\n \tmatches.) Other information, not yet supported, may be output\n \tas well, separated by single spaces.\n+\tThe output list shall be terminated with a blank line.\n \n 'import' ref::\n \tImports the given ref by outputting it in git-fast-import\n-- \n1.6.4.rc3.138.ga6b98.dirty\n"},{"id":"118861","messageId":"1248656659-21415-9-git-send-email-johan@herland.net","threadId":"20242","inReplyTo":"1248656659-21415-1-git-send-email-johan@herland.net","subject":"[RFC 08/11] Teach foreign transport code to perform the \"capabilities\" command","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T01:04:16Z","receivedAt":"2009-07-27T01:04:16Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"The features reported by the vcs helper are stored in the foreign_data struct\nwhich is expanded for this purpose.\n\nIn the process, we also change the capabilities command slightly to expect\none feature per line (instead of all features on a single line). This enables\nus to add features in the future that take one or more arguments. To terminate\nthe list of features, a blank line is output at the end.\n\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n Documentation/git-vcs.txt |    8 ++--\n transport-foreign.c       |   83 ++++++++++++++++++++++++++++++++++-----------\n 2 files changed, 67 insertions(+), 24 deletions(-)\n\ndiff --git a/Documentation/git-vcs.txt b/Documentation/git-vcs.txt\nindex febe415..85656d4 100644\n--- a/Documentation/git-vcs.txt\n+++ b/Documentation/git-vcs.txt\n@@ -33,10 +33,10 @@ The output of each command must be produced on the helper's standard output.\n The helper's standard error stream can be used for status/progress messages.\n \n 'capabilities'::\n-\tOutputs a single line with a list of feature names separated\n-\tby spaces. Each of these indicates a supported feature of the\n-\thelper, and the caller will only attempt operations that are\n-\tsupported.\n+\tOutputs a list of feature names, one per line. Each of these\n+\tindicates a supported feature of the helper, and the caller\n+\twill only attempt operations that are supported.\n+\tThe output list shall be terminated with a blank line.\n \n 'list'::\n \tOutputs the names of refs, one per line. These may be\ndiff --git a/transport-foreign.c b/transport-foreign.c\nindex 29aad77..be0a587 100644\n--- a/transport-foreign.c\n+++ b/transport-foreign.c\n@@ -8,38 +8,81 @@\n \n struct foreign_data\n {\n-\tstruct child_process *importer;\n+\tstruct child_process importer;\n+\n+\t/* capabilities */\n+\tunsigned export:1;\n+\tunsigned export_branch:1;\n+\tunsigned export_merges:1;\n };\n \n+static void get_foreign_capabilities(struct foreign_data *fdata)\n+{\n+\tstruct strbuf buf;\n+\tFILE *file;\n+\n+\twrite(fdata->importer.in, \"capabilities\\n\", 13);\n+\n+\tstrbuf_init(&buf, 0);\n+\tfile = fdopen(fdata->importer.out, \"r\");\n+\twhile (1) {\n+\t\tchar *eon;\n+\t\tif (strbuf_getline(&buf, file, '\\n') == EOF)\n+\t\t\tbreak;\n+\n+\t\tif (!*buf.buf)\n+\t\t\tbreak;\n+\n+\t\teon = strchr(buf.buf, ' ');\n+\t\tif (eon)\n+\t\t\t*eon = '\\0';\n+\n+\t\t/* parse features */\n+\t\tif (!strcmp(buf.buf, \"export\"))\n+\t\t\tfdata->export = 1;\n+\t\telse if (!strcmp(buf.buf, \"export-branch\"))\n+\t\t\tfdata->export_branch = 1;\n+\t\telse if (!strcmp(buf.buf, \"export-merges\"))\n+\t\t\tfdata->export_merges = 1;\n+\t\telse\n+\t\t\tdie(\"Invalid feature '%s'\", buf.buf);\n+\n+\t\tstrbuf_reset(&buf);\n+\t}\n+\n+\tstrbuf_release(&buf);\n+}\n+\n static struct child_process *get_importer(struct transport *transport)\n {\n-\tstruct child_process *importer = transport->data;\n-\tif (!importer) {\n+\tstruct foreign_data *fdata = (struct foreign_data *) transport->data;\n+\tif (!fdata) {\n \t\tstruct strbuf buf;\n-\t\timporter = xcalloc(1, sizeof(*importer));\n-\t\timporter->in = -1;\n-\t\timporter->out = -1;\n-\t\timporter->err = 0;\n-\t\timporter->argv = xcalloc(3, sizeof(*importer->argv));\n+\t\tfdata = xcalloc(1, sizeof(*fdata));\n+\t\tfdata->importer.in = -1;\n+\t\tfdata->importer.out = -1;\n+\t\tfdata->importer.err = 0;\n+\t\tfdata->importer.argv = xcalloc(3, sizeof(*fdata->importer.argv));\n \t\tstrbuf_init(&buf, 80);\n \t\tstrbuf_addf(&buf, \"vcs-%s\", transport->remote->foreign_vcs);\n-\t\timporter->argv[0] = buf.buf;\n-\t\timporter->argv[1] = transport->remote->name;\n-\t\timporter->git_cmd = 1;\n-\t\tstart_command(importer);\n-\t\ttransport->data = importer;\n+\t\tfdata->importer.argv[0] = buf.buf;\n+\t\tfdata->importer.argv[1] = transport->remote->name;\n+\t\tfdata->importer.git_cmd = 1;\n+\t\tstart_command(&fdata->importer);\n+\t\tget_foreign_capabilities(fdata);\n+\t\ttransport->data = fdata;\n \t}\n-\treturn importer;\n+\treturn &fdata->importer;\n }\n \n static int disconnect_foreign(struct transport *transport)\n {\n-\tstruct child_process *importer = transport->data;\n-\tif (importer) {\n-\t\twrite(importer->in, \"\\n\", 1);\n-\t\tclose(importer->in);\n-\t\tfinish_command(importer);\n-\t\tfree(importer);\n+\tstruct foreign_data *fdata = (struct foreign_data *) transport->data;\n+\tif (fdata) {\n+\t\twrite(fdata->importer.in, \"\\n\", 1);\n+\t\tclose(fdata->importer.in);\n+\t\tfinish_command(&fdata->importer);\n+\t\tfree(fdata);\n \t\ttransport->data = NULL;\n \t}\n \treturn 0;\n-- \n1.6.4.rc3.138.ga6b98.dirty\n"},{"id":"118860","messageId":"1248656659-21415-10-git-send-email-johan@herland.net","threadId":"20242","inReplyTo":"1248656659-21415-1-git-send-email-johan@herland.net","subject":"[RFC 09/11] Introduce a 'marks <filename>' feature to the foreign transport code","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T01:04:17Z","receivedAt":"2009-07-27T01:04:17Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"The 'marks' feature is reported by the vcs helper when it requires the\nfast-import marks database to loaded/saved by the git-fast-import process\nthat is executed by the foreign transport machinery. The feature is\nadvertised along with exactly one argument: the location of the file\ncontaining the marks database.\n\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n Documentation/git-vcs.txt |    8 ++++++++\n transport-foreign.c       |   32 ++++++++++++++++++++++++++++++--\n 2 files changed, 38 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-vcs.txt b/Documentation/git-vcs.txt\nindex 85656d4..75815ba 100644\n--- a/Documentation/git-vcs.txt\n+++ b/Documentation/git-vcs.txt\n@@ -65,6 +65,14 @@ there may be other restrictions on what may be exported.\n FEATURES\n --------\n \n+'marks' filename::\n+\tHelper requires the marks from a git-fast-import run to be loaded\n+\tfrom, and saved to, the given filename. When this \"feature\" is\n+\tadvertised, each git-fast-import run must load and save the\n+\tinternal marks database (see the --import-marks and --export-marks\n+\toption to git-fast-import for more details) located at the given\n+\tfilename.\n+\n 'export'::\n \tHelper supports exporting commits, at least exporting\n \tnon-merge commits whose parents are not the parents of any\ndiff --git a/transport-foreign.c b/transport-foreign.c\nindex be0a587..ae9cb9a 100644\n--- a/transport-foreign.c\n+++ b/transport-foreign.c\n@@ -11,6 +11,7 @@ struct foreign_data\n \tstruct child_process importer;\n \n \t/* capabilities */\n+\tchar *marks_filename;\n \tunsigned export:1;\n \tunsigned export_branch:1;\n \tunsigned export_merges:1;\n@@ -38,7 +39,12 @@ static void get_foreign_capabilities(struct foreign_data *fdata)\n \t\t\t*eon = '\\0';\n \n \t\t/* parse features */\n-\t\tif (!strcmp(buf.buf, \"export\"))\n+\t\tif (!strcmp(buf.buf, \"marks\")) {\n+\t\t\tif (!eon)\n+\t\t\t\tdie(\"Feature 'marks' requires an argument\");\n+\t\t\tfdata->marks_filename = xstrdup(eon + 1);\n+\t\t}\n+\t\telse if (!strcmp(buf.buf, \"export\"))\n \t\t\tfdata->export = 1;\n \t\telse if (!strcmp(buf.buf, \"export-branch\"))\n \t\t\tfdata->export_branch = 1;\n@@ -82,6 +88,7 @@ static int disconnect_foreign(struct transport *transport)\n \t\twrite(fdata->importer.in, \"\\n\", 1);\n \t\tclose(fdata->importer.in);\n \t\tfinish_command(&fdata->importer);\n+\t\tfree(fdata->marks_filename);\n \t\tfree(fdata);\n \t\ttransport->data = NULL;\n \t}\n@@ -91,10 +98,13 @@ static int disconnect_foreign(struct transport *transport)\n static int fetch_refs_via_foreign(struct transport *transport,\n \t\t\t\t  int nr_heads, struct ref **to_fetch)\n {\n+\tstruct foreign_data *fdata;\n \tstruct child_process *importer;\n \tstruct child_process fastimport;\n \tstruct ref *posn;\n+\tstruct strbuf export_marks, import_marks;\n \tint i, count;\n+\tFILE *f;\n \n \tcount = 0;\n \tfor (i = 0; i < nr_heads; i++) {\n@@ -105,12 +115,28 @@ static int fetch_refs_via_foreign(struct transport *transport,\n \t}\n \tif (count) {\n \t\timporter = get_importer(transport);\n+\t\tfdata = (struct foreign_data *) transport->data;\n+\t\tstrbuf_init(&export_marks, 0);\n+\t\tstrbuf_init(&import_marks, 0);\n \n \t\tmemset(&fastimport, 0, sizeof(fastimport));\n \t\tfastimport.in = importer->out;\n-\t\tfastimport.argv = xcalloc(3, sizeof(*fastimport.argv));\n+\t\tfastimport.argv = xcalloc(5, sizeof(*fastimport.argv));\n \t\tfastimport.argv[0] = \"fast-import\";\n \t\tfastimport.argv[1] = \"--quiet\";\n+\t\tif (fdata->marks_filename) {\n+\t\t\tstrbuf_addf(&export_marks, \"--export-marks=%s\",\n+\t\t\t\tfdata->marks_filename);\n+\t\t\tfastimport.argv[2] = export_marks.buf;\n+\n+\t\t\tf = fopen(fdata->marks_filename, \"r\");\n+\t\t\tif (f) {\n+\t\t\t\tstrbuf_addf(&import_marks, \"--import-marks=%s\",\n+\t\t\t\t\tfdata->marks_filename);\n+\t\t\t\tfastimport.argv[3] = import_marks.buf;\n+\t\t\t\tfclose(f);\n+\t\t\t}\n+\t\t}\n \t\tfastimport.git_cmd = 1;\n \t\tstart_command(&fastimport);\n \n@@ -124,6 +150,8 @@ static int fetch_refs_via_foreign(struct transport *transport,\n \t\t}\n \t\tdisconnect_foreign(transport);\n \t\tfinish_command(&fastimport);\n+\t\tstrbuf_release(&export_marks);\n+\t\tstrbuf_release(&import_marks);\n \t}\n \tfor (i = 0; i < nr_heads; i++) {\n \t\tposn = to_fetch[i];\n-- \n1.6.4.rc3.138.ga6b98.dirty\n"},{"id":"118862","messageId":"1248656659-21415-12-git-send-email-johan@herland.net","threadId":"20242","inReplyTo":"1248656659-21415-1-git-send-email-johan@herland.net","subject":"[RFC 11/11] Add simple test cases of git-vcs-cvs functionality","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T01:04:19Z","receivedAt":"2009-07-27T01:04:19Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"Signed-off-by: Johan Herland <johan@herland.net>\n---\n t/t9800-foreign-vcs-cvs-basic.sh |  518 ++++++++++++++++++++++++++++++++++++++\n t/t9801-foreign-vcs-cvs-fetch.sh |  291 +++++++++++++++++++++\n t/test-lib.sh                    |    1 +\n 3 files changed, 810 insertions(+), 0 deletions(-)\n create mode 100755 t/t9800-foreign-vcs-cvs-basic.sh\n create mode 100755 t/t9801-foreign-vcs-cvs-fetch.sh\n\ndiff --git a/t/t9800-foreign-vcs-cvs-basic.sh b/t/t9800-foreign-vcs-cvs-basic.sh\nnew file mode 100755\nindex 0000000..4e29e62\n--- /dev/null\n+++ b/t/t9800-foreign-vcs-cvs-basic.sh\n@@ -0,0 +1,518 @@\n+#!/bin/sh\n+\n+test_description='git vcs-cvs basic tests'\n+. ./test-lib.sh\n+\n+if ! test_have_prereq PYTHON; then\n+\tsay 'skipping CVS foreign-vcs helper tests, python not available'\n+\ttest_done\n+fi\n+\n+CVS_EXEC=cvs\n+CVS_OPTS=\"-f -q\"\n+CVS=\"$CVS_EXEC $CVS_OPTS\"\n+\n+CVSROOT=$(pwd)/cvsroot\n+export CVSROOT\n+unset CVS_SERVER\n+\n+CVSMODULE=cvsmodule\n+GITREMOTE=cvsremote\n+\n+if ! type $CVS_EXEC >/dev/null 2>&1\n+then\n+\tsay 'skipping vcs-cvs tests, $CVS_EXEC not found'\n+\ttest_done\n+fi\n+\n+test_expect_success 'setup cvsroot' '$CVS init'\n+\n+test_expect_success '#1: setup a cvs module' '\n+\n+\tmkdir \"$CVSROOT/$CVSMODULE\" &&\n+\t$CVS co -d module-cvs $CVSMODULE &&\n+\t(\n+\t\tcd module-cvs &&\n+\t\tcat <<EOF >o_fortuna &&\n+O Fortuna\n+velut luna\n+statu variabilis,\n+\n+semper crescis\n+aut decrescis;\n+vita detestabilis\n+\n+nunc obdurat\n+et tunc curat\n+ludo mentis aciem,\n+\n+egestatem,\n+potestatem\n+dissolvit ut glaciem.\n+EOF\n+\t\t$CVS add o_fortuna &&\n+\t\tcat <<EOF >message &&\n+add \"O Fortuna\" lyrics\n+\n+These public domain lyrics make an excellent sample text.\n+EOF\n+\t\t$CVS commit -f -F message o_fortuna\n+\t)\n+'\n+\n+test_expect_success 'set up CVS repo as a foreign remote' '\n+\n+\tgit config \"user.name\" \"Test User\"\n+\tgit config \"user.email\" \"test@example.com\"\n+\tgit config \"remote.$GITREMOTE.vcs\" cvs\n+\tgit config \"remote.$GITREMOTE.cvsRoot\" \"$CVSROOT\"\n+\tgit config \"remote.$GITREMOTE.cvsModule\" \"$CVSMODULE\"\n+\tgit config \"remote.$GITREMOTE.fetch\" \\\n+\t\t\"+refs/cvs/$GITREMOTE/*:refs/remotes/$GITREMOTE/*\"\n+\n+'\n+\n+test_expect_success '#1: git-vcs-cvs \"capabilities\" command' '\n+\n+\techo \"capabilities\" | git vcs-cvs \"$GITREMOTE\" > actual &&\n+\tcat <<EOF >expect &&\n+marks .git/info/cvs/$GITREMOTE/marks\n+\n+EOF\n+\ttest_cmp expect actual\n+\n+'\n+\n+test_expect_success '#1: git-vcs-cvs \"list\" command' '\n+\n+\techo \"list\" | git vcs-cvs \"$GITREMOTE\" > actual &&\n+\tcat <<EOF >expect &&\n+refs/cvs/$GITREMOTE/HEAD changed\n+\n+EOF\n+\ttest_cmp expect actual\n+\n+'\n+\n+test_expect_success '#1: git-vcs-cvs \"import\" command' '\n+\n+\techo \"import refs/cvs/$GITREMOTE/HEAD\" | git vcs-cvs \"$GITREMOTE\" > actual &&\n+\tcat <<EOF >expect &&\n+# Importing CVS revision o_fortuna:1.1\n+blob\n+mark :1\n+data 180\n+O Fortuna\n+velut luna\n+statu variabilis,\n+\n+semper crescis\n+aut decrescis;\n+vita detestabilis\n+\n+nunc obdurat\n+et tunc curat\n+ludo mentis aciem,\n+\n+egestatem,\n+potestatem\n+dissolvit ut glaciem.\n+\n+commit refs/cvs/$GITREMOTE/HEAD\n+mark :2\n+data 82\n+add \"O Fortuna\" lyrics\n+\n+These public domain lyrics make an excellent sample text.\n+\n+M 644 :1 o_fortuna\n+\n+# Importing note for object 2\n+blob\n+mark :3\n+data 14\n+o_fortuna:1.1\n+\n+commit refs/notes/cvs/$GITREMOTE\n+mark :4\n+data 43\n+Annotate commits imported by \"git vcs-cvs\"\n+\n+M 644 :3 :2\n+\n+blob\n+mark :5\n+data 32\n+1 o_fortuna:1.1\n+2 o_fortuna:1.1\n+\n+blob\n+mark :6\n+data 16\n+blob 1\n+commit 2\n+\n+commit refs/cvs/$GITREMOTE/_metadata\n+mark :7\n+data 39\n+Updated metadata used by \"git vcs-cvs\"\n+\n+M 644 :5 CVS/marks\n+M 644 :6 o_fortuna/1.1\n+\n+EOF\n+\tgrep -v \"^committer \" actual > actual.filtered &&\n+\ttest_cmp expect actual.filtered\n+\n+'\n+\n+test_expect_success '#1: Passing git-vcs-cvs output to git-fast-import' '\n+\n+\tgit fast-import --quiet \\\n+\t\t--export-marks=\".git/info/cvs/$GITREMOTE/marks\" \\\n+\t\t< actual &&\n+\tgit gc\n+\n+'\n+\n+test_expect_success '#1: Verifying correctness of import' '\n+\n+\techo \"verify HEAD\" | git vcs-cvs \"$GITREMOTE\"\n+\n+'\n+\n+test_expect_success '#2: update cvs module' '\n+\n+\t(\n+\t\tcd module-cvs &&\n+\t\tcat <<EOF >o_fortuna &&\n+O Fortune,\n+like the moon\n+you are changeable,\n+\n+ever waxing\n+and waning;\n+hateful life\n+\n+first oppresses\n+and then soothes\n+as fancy takes it;\n+\n+poverty\n+and power\n+it melts them like ice.\n+EOF\n+\t\tcat <<EOF >message &&\n+translate to English\n+\n+My Latin is terrible.\n+EOF\n+\t\t$CVS commit -f -F message o_fortuna\n+\t)\n+'\n+\n+test_expect_success '#2: git-vcs-cvs \"capabilities\" command' '\n+\n+\techo \"capabilities\" | git vcs-cvs \"$GITREMOTE\" > actual &&\n+\tcat <<EOF >expect &&\n+marks .git/info/cvs/$GITREMOTE/marks\n+\n+EOF\n+\ttest_cmp expect actual\n+\n+'\n+\n+test_expect_success '#2: git-vcs-cvs \"list\" command' '\n+\n+\techo \"list\" | git vcs-cvs \"$GITREMOTE\" > actual &&\n+\tcat <<EOF >expect &&\n+refs/cvs/$GITREMOTE/HEAD changed\n+\n+EOF\n+\ttest_cmp expect actual\n+\n+'\n+\n+test_expect_success '#2: git-vcs-cvs \"import\" command' '\n+\n+\techo \"import refs/cvs/$GITREMOTE/HEAD\" | git vcs-cvs \"$GITREMOTE\" > actual &&\n+\tcat <<EOF >expect &&\n+# Importing CVS revision o_fortuna:1.2\n+blob\n+mark :8\n+data 179\n+O Fortune,\n+like the moon\n+you are changeable,\n+\n+ever waxing\n+and waning;\n+hateful life\n+\n+first oppresses\n+and then soothes\n+as fancy takes it;\n+\n+poverty\n+and power\n+it melts them like ice.\n+\n+commit refs/cvs/$GITREMOTE/HEAD\n+mark :9\n+data 44\n+translate to English\n+\n+My Latin is terrible.\n+\n+from refs/cvs/$GITREMOTE/HEAD^0\n+M 644 :8 o_fortuna\n+\n+# Importing note for object 9\n+blob\n+mark :10\n+data 14\n+o_fortuna:1.2\n+\n+commit refs/notes/cvs/$GITREMOTE\n+mark :11\n+data 43\n+Annotate commits imported by \"git vcs-cvs\"\n+\n+from refs/notes/cvs/$GITREMOTE^0\n+M 644 :10 :9\n+\n+blob\n+mark :12\n+data 32\n+8 o_fortuna:1.2\n+9 o_fortuna:1.2\n+\n+blob\n+mark :13\n+data 94\n+\n+blob\n+mark :14\n+data 16\n+blob 8\n+commit 9\n+\n+commit refs/cvs/$GITREMOTE/_metadata\n+mark :15\n+data 39\n+Updated metadata used by \"git vcs-cvs\"\n+\n+from refs/cvs/$GITREMOTE/_metadata^0\n+M 644 :12 CVS/marks\n+M 644 :13 o_fortuna/1.1\n+M 644 :14 o_fortuna/1.2\n+\n+EOF\n+\tgrep -v -e \"^committer \" -e \"\\b[0-9a-f]\\{40\\}\\b\" actual > actual.filtered &&\n+\ttest_cmp expect actual.filtered\n+\n+'\n+\n+test_expect_success '#2: Passing git-vcs-cvs output to git-fast-import' '\n+\n+\tgit fast-import --quiet \\\n+\t\t--import-marks=\".git/info/cvs/$GITREMOTE/marks\" \\\n+\t\t--export-marks=\".git/info/cvs/$GITREMOTE/marks\" \\\n+\t\t< actual &&\n+\tgit gc\n+\n+'\n+\n+test_expect_success '#2: Verifying correctness of import' '\n+\n+\techo \"verify HEAD\" | git vcs-cvs \"$GITREMOTE\"\n+\n+'\n+\n+test_expect_success '#3: update cvs module' '\n+\n+\t(\n+\t\tcd module-cvs &&\n+\t\techo 1 >tick &&\n+\t\t$CVS add tick &&\n+\t\t$CVS commit -f -m 1 tick\n+\t)\n+\n+'\n+\n+test_expect_success '#3: git-vcs-cvs \"capabilities\" command' '\n+\n+\techo \"capabilities\" | git vcs-cvs \"$GITREMOTE\" > actual &&\n+\tcat <<EOF >expect &&\n+marks .git/info/cvs/$GITREMOTE/marks\n+\n+EOF\n+\ttest_cmp expect actual\n+\n+'\n+\n+test_expect_success '#3: git-vcs-cvs \"list\" command' '\n+\n+\techo \"list\" | git vcs-cvs \"$GITREMOTE\" > actual &&\n+\tcat <<EOF >expect &&\n+refs/cvs/$GITREMOTE/HEAD changed\n+\n+EOF\n+\ttest_cmp expect actual\n+\n+'\n+\n+test_expect_success '#3: git-vcs-cvs \"import\" command' '\n+\n+\techo \"import refs/cvs/$GITREMOTE/HEAD\" | git vcs-cvs \"$GITREMOTE\" > actual &&\n+\tcat <<EOF >expect &&\n+# Importing CVS revision tick:1.1\n+blob\n+mark :16\n+data 2\n+1\n+\n+commit refs/cvs/$GITREMOTE/HEAD\n+mark :17\n+data 2\n+1\n+\n+from refs/cvs/$GITREMOTE/HEAD^0\n+M 644 :16 tick\n+\n+# Importing note for object 17\n+blob\n+mark :18\n+data 23\n+o_fortuna:1.2\n+tick:1.1\n+\n+commit refs/notes/cvs/$GITREMOTE\n+mark :19\n+data 43\n+Annotate commits imported by \"git vcs-cvs\"\n+\n+from refs/notes/cvs/$GITREMOTE^0\n+M 644 :18 :17\n+\n+blob\n+mark :20\n+data 41\n+16 tick:1.1\n+17 tick:1.1\n+17 o_fortuna:1.2\n+\n+blob\n+mark :21\n+data 104\n+commit 17\n+\n+blob\n+mark :22\n+data 18\n+blob 16\n+commit 17\n+\n+commit refs/cvs/$GITREMOTE/_metadata\n+mark :23\n+data 39\n+Updated metadata used by \"git vcs-cvs\"\n+\n+from refs/cvs/$GITREMOTE/_metadata^0\n+M 644 :20 CVS/marks\n+M 644 :21 o_fortuna/1.2\n+M 644 :22 tick/1.1\n+\n+EOF\n+\tgrep -v -e \"^committer \" -e \"\\b[0-9a-f]\\{40\\}\\b\" actual > actual.filtered &&\n+\ttest_cmp expect actual.filtered\n+\n+'\n+\n+test_expect_success '#3: Passing git-vcs-cvs output to git-fast-import' '\n+\n+\tgit fast-import --quiet \\\n+\t\t--import-marks=\".git/info/cvs/$GITREMOTE/marks\" \\\n+\t\t--export-marks=\".git/info/cvs/$GITREMOTE/marks\" \\\n+\t\t< actual &&\n+\tgit gc\n+\n+'\n+\n+test_expect_success '#3: Verifying correctness of import' '\n+\n+\techo \"verify HEAD\" | git vcs-cvs \"$GITREMOTE\"\n+\n+'\n+\n+test_expect_success '#4: git-vcs-cvs \"capabilities\" command' '\n+\n+\techo \"capabilities\" | git vcs-cvs \"$GITREMOTE\" > actual &&\n+\tcat <<EOF >expect &&\n+marks .git/info/cvs/$GITREMOTE/marks\n+\n+EOF\n+\ttest_cmp expect actual\n+\n+'\n+\n+test_expect_success '#4: git-vcs-cvs \"list\" command' '\n+\n+\techo \"list\" | git vcs-cvs \"$GITREMOTE\" > actual &&\n+\tcat <<EOF >expect &&\n+refs/cvs/$GITREMOTE/HEAD unchanged\n+\n+EOF\n+\ttest_cmp expect actual\n+\n+'\n+\n+test_expect_success '#4: git-vcs-cvs \"import\" command' '\n+\n+\techo \"import refs/cvs/$GITREMOTE/HEAD\" | git vcs-cvs \"$GITREMOTE\" > actual &&\n+\tcat <<EOF >expect &&\n+blob\n+mark :24\n+data 0\n+\n+blob\n+mark :25\n+data 142\n+\n+blob\n+mark :26\n+data 94\n+\n+commit refs/cvs/$GITREMOTE/_metadata\n+mark :27\n+data 39\n+Updated metadata used by \"git vcs-cvs\"\n+\n+from refs/cvs/$GITREMOTE/_metadata^0\n+M 644 :24 CVS/marks\n+M 644 :25 o_fortuna/1.2\n+M 644 :26 tick/1.1\n+\n+EOF\n+\tgrep -v -e \"^committer \" -e \"\\b[0-9a-f]\\{40\\}\\b\" actual > actual.filtered &&\n+\ttest_cmp expect actual.filtered\n+\n+'\n+\n+test_expect_success '#4: Passing git-vcs-cvs output to git-fast-import' '\n+\n+\tgit fast-import --quiet \\\n+\t\t--import-marks=\".git/info/cvs/$GITREMOTE/marks\" \\\n+\t\t--export-marks=\".git/info/cvs/$GITREMOTE/marks\" \\\n+\t\t< actual &&\n+\tgit gc\n+\n+'\n+\n+test_expect_success '#4: Verifying correctness of import' '\n+\n+\techo \"verify HEAD\" | git vcs-cvs \"$GITREMOTE\"\n+\n+'\n+\n+test_done\ndiff --git a/t/t9801-foreign-vcs-cvs-fetch.sh b/t/t9801-foreign-vcs-cvs-fetch.sh\nnew file mode 100755\nindex 0000000..62a2325\n--- /dev/null\n+++ b/t/t9801-foreign-vcs-cvs-fetch.sh\n@@ -0,0 +1,291 @@\n+#!/bin/sh\n+\n+test_description='git vcs-cvs basic tests'\n+. ./test-lib.sh\n+\n+if ! test_have_prereq PYTHON; then\n+\tsay 'skipping CVS foreign-vcs helper tests, python not available'\n+\ttest_done\n+fi\n+\n+CVS_EXEC=cvs\n+CVS_OPTS=\"-f -q\"\n+CVS=\"$CVS_EXEC $CVS_OPTS\"\n+\n+CVSROOT=$(pwd)/cvsroot\n+export CVSROOT\n+unset CVS_SERVER\n+\n+CVSMODULE=cvsmodule\n+GITREMOTE=cvsremote\n+\n+if ! type $CVS_EXEC >/dev/null 2>&1\n+then\n+\tsay 'skipping vcs-cvs tests, $CVS_EXEC not found'\n+\ttest_done\n+fi\n+\n+verify () {\n+\tgit log --reverse --format=\"--- %T%n%s%n%n%b\" \"$GITREMOTE/$1\" >actual &&\n+\ttest_cmp \"expect.$1\" actual &&\n+\techo \"verify $1\" | git vcs-cvs \"$GITREMOTE\"\n+}\n+\n+test_expect_success 'setup CVS repo' '$CVS init'\n+\n+test_expect_success 'create CVS module with initial commit' '\n+\n+\tmkdir \"$CVSROOT/$CVSMODULE\" &&\n+\t$CVS co -d module-cvs $CVSMODULE &&\n+\t(\n+\t\tcd module-cvs &&\n+\t\tcat <<EOF >o_fortuna &&\n+O Fortuna\n+velut luna\n+statu variabilis,\n+\n+semper crescis\n+aut decrescis;\n+vita detestabilis\n+\n+nunc obdurat\n+et tunc curat\n+ludo mentis aciem,\n+\n+egestatem,\n+potestatem\n+dissolvit ut glaciem.\n+EOF\n+\t\t$CVS add o_fortuna &&\n+\t\tcat <<EOF >message &&\n+add \"O Fortuna\" lyrics\n+\n+These public domain lyrics make an excellent sample text.\n+EOF\n+\t\t$CVS commit -f -F message o_fortuna\n+\t)\n+'\n+\n+test_expect_success 'set up CVS repo/module as a foreign remote' '\n+\n+\tgit config \"user.name\" \"Test User\"\n+\tgit config \"user.email\" \"test@example.com\"\n+\tgit config \"remote.$GITREMOTE.vcs\" cvs\n+\tgit config \"remote.$GITREMOTE.cvsRoot\" \"$CVSROOT\"\n+\tgit config \"remote.$GITREMOTE.cvsModule\" \"$CVSMODULE\"\n+\tgit config \"remote.$GITREMOTE.fetch\" \\\n+\t\t\"+refs/cvs/$GITREMOTE/*:refs/remotes/$GITREMOTE/*\"\n+\n+'\n+\n+test_expect_success 'initial fetch from CVS remote' '\n+\n+\tcat <<EOF >expect.HEAD &&\n+--- 0e06d780dedab23e683c686fb041daa9a84c936c\n+add \"O Fortuna\" lyrics\n+\n+These public domain lyrics make an excellent sample text.\n+\n+EOF\n+\tgit fetch \"$GITREMOTE\" &&\n+\tverify HEAD\n+\n+'\n+\n+test_expect_success 'CVS commit' '\n+\n+\t(\n+\t\tcd module-cvs &&\n+\t\tcat <<EOF >o_fortuna &&\n+O Fortune,\n+like the moon\n+you are changeable,\n+\n+ever waxing\n+and waning;\n+hateful life\n+\n+first oppresses\n+and then soothes\n+as fancy takes it;\n+\n+poverty\n+and power\n+it melts them like ice.\n+EOF\n+\t\tcat <<EOF >message &&\n+translate to English\n+\n+My Latin is terrible.\n+EOF\n+\t\t$CVS commit -f -F message o_fortuna\n+\t) &&\n+\tcat <<EOF >>expect.HEAD &&\n+--- daa87269a5e00388135ad9542dc16ab6754466e5\n+translate to English\n+\n+My Latin is terrible.\n+\n+EOF\n+\tgit fetch \"$GITREMOTE\" &&\n+\tverify HEAD\n+\n+'\n+\n+test_expect_success 'CVS commit with new file' '\n+\n+\t(\n+\t\tcd module-cvs &&\n+\t\techo 1 >tick &&\n+\t\t$CVS add tick &&\n+\t\t$CVS commit -f -m 1 tick\n+\t) &&\n+\tcat <<EOF >>expect.HEAD &&\n+--- 486935b4fccecea9b64cbed3a797ebbcbe2b7461\n+1\n+\n+\n+EOF\n+\tgit fetch \"$GITREMOTE\" &&\n+\tverify HEAD\n+\n+'\n+\n+test_expect_success 'fetch without CVS changes' '\n+\n+\tgit fetch \"$GITREMOTE\" &&\n+\tverify HEAD\n+\n+'\n+\n+test_expect_success 'add 2 CVS commits' '\n+\n+\t(\n+\t\tcd module-cvs &&\n+\t\techo 2 >tick &&\n+\t\t$CVS commit -f -m 2 tick &&\n+\t\techo 3 >tick &&\n+\t\t$CVS commit -f -m 3 tick\n+\t) &&\n+\tcat <<EOF >>expect.HEAD &&\n+--- 83437ab3e57bf0a42915de5310e3419792b5a36f\n+2\n+\n+\n+--- 60fc50406a82dc6bd32dc6e5f7bd23e4c3cdf7ef\n+3\n+\n+\n+EOF\n+\tgit fetch \"$GITREMOTE\" &&\n+\tverify HEAD\n+\n+'\n+\n+test_expect_success 'CVS commit with removed file' '\n+\n+\t(\n+\t\tcd module-cvs &&\n+\t\t$CVS remove -f tick &&\n+\t\t$CVS commit -f -m \"remove file\" tick\n+\t) &&\n+\tcat <<EOF >>expect.HEAD &&\n+--- daa87269a5e00388135ad9542dc16ab6754466e5\n+remove file\n+\n+\n+EOF\n+\tgit fetch \"$GITREMOTE\" &&\n+\tverify HEAD\n+\n+'\n+\n+test_expect_success 'CVS commit with several new files' '\n+\n+\t(\n+\t\tcd module-cvs &&\n+\t\techo spam >spam &&\n+\t\techo sausage >sausage &&\n+\t\techo eggs >eggs &&\n+\t\t$CVS add spam sausage eggs &&\n+\t\t$CVS commit -f -m \"spam, sausage, and eggs\" spam sausage eggs\n+\t) &&\n+\tcat <<EOF >>expect.HEAD &&\n+--- 3190dfce44a6d5e9916b4870dbf8f37d1ca4ddaf\n+spam, sausage, and eggs\n+\n+\n+EOF\n+\tgit fetch \"$GITREMOTE\" &&\n+\tverify HEAD\n+\n+'\n+\n+test_expect_success 'new CVS branch' '\n+\n+\t(\n+\t\tcd module-cvs &&\n+\t\t$CVS tag -b foo\n+\t) &&\n+\tcp expect.HEAD expect.foo &&\n+\tgit fetch \"$GITREMOTE\" &&\n+\tverify HEAD &&\n+\tverify foo\n+\n+'\n+\n+test_expect_success 'CVS commit on branch' '\n+\n+\t(\n+\t\tcd module-cvs &&\n+\t\t$CVS up -r foo &&\n+\t\techo \"spam spam spam\" >spam &&\n+\t\t$CVS commit -f -m \"commit on branch foo\" spam\n+\t) &&\n+\tcat <<EOF >>expect.foo &&\n+--- 1aba123e5c83898ce3a8b976cc6064d60246aef4\n+commit on branch foo\n+\n+\n+EOF\n+\tgit fetch \"$GITREMOTE\" &&\n+\tverify HEAD &&\n+\tverify foo\n+\n+'\n+\n+test_expect_success 'create CVS tag' '\n+\n+\t(\n+\t\tcd module-cvs &&\n+\t\t$CVS tag bar\n+\t) &&\n+\tcp expect.foo expect.bar &&\n+\tgit fetch \"$GITREMOTE\" &&\n+\tverify HEAD &&\n+\tverify foo &&\n+\tverify bar\n+\n+'\n+\n+test_expect_success 'another CVS commit on branch' '\n+\n+\t(\n+\t\tcd module-cvs &&\n+\t\techo \"spam spam spam spam spam spam\" >> spam &&\n+\t\t$CVS commit -f -m \"another commit on branch foo\" spam\n+\t) &&\n+\tcat <<EOF >>expect.foo &&\n+--- 15a2635e76e8e5a5a8746021643de317452f2340\n+another commit on branch foo\n+\n+\n+EOF\n+\tgit fetch \"$GITREMOTE\" &&\n+\tverify HEAD &&\n+\tverify foo &&\n+\tverify bar\n+\n+'\n+\n+test_done\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 5fdc5d9..8eb8b95 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -706,6 +706,7 @@ case $(uname -s) in\n esac\n \n test -z \"$NO_PERL\" && test_set_prereq PERL\n+test -z \"$NO_PYTHON\" && test_set_prereq PYTHON\n \n # test whether the filesystem supports symbolic links\n ln -s x y 2>/dev/null && test -h y 2>/dev/null && test_set_prereq SYMLINKS\n-- \n1.6.4.rc3.138.ga6b98.dirty\n"},{"id":"118878","messageId":"20090727141200.GJ11191@spearce.org","threadId":"20242","inReplyTo":"1248656659-21415-7-git-send-email-johan@herland.net","subject":"Re: [RFC 06/11] Add support for mark references as path names","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-07-27T14:12:00Z","receivedAt":"2009-07-27T14:12:00Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Johan Herland <johan@herland.net> wrote:\n> When using a mark reference as a path name, the mark reference will be\n> expanded to the 40-byte hex version of the object name associated with the\n> mark. This is useful e.g. when importing notes objects (where the filenames\n> in a notes tree are the object names of the annotated objects).\n> \n> Signed-off-by: Johan Herland <johan@herland.net>\n> ---\n>  Documentation/git-fast-import.txt |    9 +++++++--\n>  fast-import.c                     |   11 +++++++++--\n>  2 files changed, 16 insertions(+), 4 deletions(-)\n> \n> diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\n> index c2f483a..bbc8b78 100644\n> --- a/Documentation/git-fast-import.txt\n> +++ b/Documentation/git-fast-import.txt\n> @@ -487,12 +487,17 @@ in octal.  Git only supports the following modes:\n>  \n>  In both formats `<path>` is the complete path of the file to be added\n>  (if not already existing) or modified (if already existing).\n> +`<path>` may also be a mark reference (`:<idnum>`) set by a prior\n> +command, which will expand to a full 40-byte SHA-1 of the Git object\n> +associated with the mark. This is useful e.g. when importing commit\n> +notes (the filenames in a notes commit are the object names of the\n> +annotated commits).\n>  \n>  A `<path>` string must use UNIX-style directory separators (forward\n>  slash `/`), may contain any byte other than `LF`, and must not\n> -start with double quote (`\"`).\n> +start with double quote (`\"`) or colon (`:`).\n\nI'm worried about changing the path rules here.  Previously writing\na path as :1 was legal and produced a file named \":1\" in the top\nlevel directory of the repository.  Now it will create a file that\nmatches a mark.\n\nI think you need to find another back door, something that the\nlanguage wouldn't have considered as valid previously.\n  \n-- \nShawn.\n"},{"id":"118883","messageId":"alpine.LNX.2.00.0907271251280.2147@iabervon.org","threadId":"20242","inReplyTo":"1248656659-21415-1-git-send-email-johan@herland.net","subject":"Re: [RFC 00/11] Foreign VCS helper program for CVS repositories","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2009-07-27T17:27:47Z","receivedAt":"2009-07-27T17:27:47Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Mon, 27 Jul 2009, Johan Herland wrote:\n\n> This series is a first draft towards implementing a foreign VCS helper\n> program for CVS.\n> \n> It is based on the 'db/foreign-scm' and 'jh/notes' topics in 'pu'. As such,\n> this patch series should apply cleanly to current 'pu'.\n> \n> The first 4 patches supply the necessary parts of Daniel Barkalow's\n> foreign-scm topic that has not yet been merged to 'pu' (i.e. everything\n> remaining in Daniel's original patch series, except the p4-specific stuff).\n\nI've got some changes to this series in the works; I just made a few \nchanges to share the transport-side code for interacting with the helper \nwith the transport-side code for interacting with native-object helpers. \nMainly, this means starting each line in the \"list\" response with \"?\" to \nindicate that you don't know the hash, since the protocol is trying to be \ncompatible with cases where you do know.\n\n> The next 2 patches add some functionality to git fast-import, for\n> facilitating the import of 'notes' objects (this is a _much_ faster way to\n> generate/import notes than invoking \"git notes edit -m MSG\" for each note).\n> \n> Next, there are 3 patches tweaking and expanding the git-vcs API (with\n> corresponding implementations in the foreign transport code) to adjust for\n> the CVS helper's needs.\n\nThese make sense to me. I assume you're planning to support exporting in \nsome ways, but haven't got it working yet? I largely ignored the \ncapabilities stuff because I didn't have two systems with differing \nrequirements to actually use it.\n\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"118888","messageId":"200907272011.19430.johan@herland.net","threadId":"20242","inReplyTo":"alpine.LNX.2.00.0907271251280.2147@iabervon.org","subject":"Re: [RFC 00/11] Foreign VCS helper program for CVS repositories","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T18:11:19Z","receivedAt":"2009-07-27T18:11:19Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Monday 27 July 2009, Daniel Barkalow wrote:\n> On Mon, 27 Jul 2009, Johan Herland wrote:\n> > This series is a first draft towards implementing a foreign VCS\n> > helper program for CVS.\n> >\n> > It is based on the 'db/foreign-scm' and 'jh/notes' topics in 'pu'.\n> > As such, this patch series should apply cleanly to current 'pu'.\n> >\n> > The first 4 patches supply the necessary parts of Daniel Barkalow's\n> > foreign-scm topic that has not yet been merged to 'pu' (i.e.\n> > everything remaining in Daniel's original patch series, except the\n> > p4-specific stuff).\n>\n> I've got some changes to this series in the works; I just made a few\n> changes to share the transport-side code for interacting with the\n> helper with the transport-side code for interacting with\n> native-object helpers. Mainly, this means starting each line in the\n> \"list\" response with \"?\" to indicate that you don't know the hash,\n> since the protocol is trying to be compatible with cases where you do\n> know.\n\nNo problem. I'm actually considering whether I should rewrite the CVS \nhelper to a full-fledged git-shim (btw, thanks for the shim work; it \nlooks really promising). I would still probably have to use \ngit-fast-import, but I would have more control over the fast-import \nprocess (e.g. by closing the fast-import process myself, I could \nsimplify the code maintaining the marks database).\n\nWith the git-shim feature already having found an excellent use case \n(the HTTP fetcher), how do you see the future for the foreign-scm \ntopic? I like the idea of rewriting foreign-scm on top of git-shim, but \nis there anything substantial _left_ in foreign-scm after such a \nrewrite?\n\n> > Next, there are 3 patches tweaking and expanding the git-vcs API\n> > (with corresponding implementations in the foreign transport code)\n> > to adjust for the CVS helper's needs.\n>\n> These make sense to me. I assume you're planning to support exporting\n> in some ways, but haven't got it working yet?\n\nIndeed. The current version is only a first draft that fetches \nsuccessfully from simple toy repositories (but probably not many \nreal-world CVS repos). I hope to support both fetching and pushing to \nreal-world CVS repos at some point.\n\n\nHave fun! :)\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"118890","messageId":"200907272026.46150.johan@herland.net","threadId":"20242","inReplyTo":"20090727141200.GJ11191@spearce.org","subject":"Re: [RFC 06/11] Add support for mark references as path names","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-27T18:26:45Z","receivedAt":"2009-07-27T18:26:45Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Monday 27 July 2009, Shawn O. Pearce wrote:\n> Johan Herland <johan@herland.net> wrote:\n> > When using a mark reference as a path name, the mark reference will\n> > be expanded to the 40-byte hex version of the object name\n> > associated with the mark. This is useful e.g. when importing notes\n> > objects (where the filenames in a notes tree are the object names\n> > of the annotated objects).\n> >\n> > [...cut...]\n>\n> I'm worried about changing the path rules here.  Previously writing\n> a path as :1 was legal and produced a file named \":1\" in the top\n> level directory of the repository.  Now it will create a file that\n> matches a mark.\n>\n> I think you need to find another back door, something that the\n> language wouldn't have considered as valid previously.\n\nOk. One (moderately hideous) option is to introduce new commands m/d/r/c \nthat works just like M/D/R/C, except that they also expand mark \nreferences (leaving M/D/R/C with the old behaviour). I don't know how \nyou'd feel about that...\n\nHowever, I'm also pondering Dscho's idea of organizing note trees into \nhierarchies (to limit #entries in tree objects), and (although I have \nyet to try to implement this) it feels like this transformation should \nbe done in the notes.c code, which means that it must happen on \nthe \"git side\" of fast-import (at least the transformation should not \nhappen on the \"external side\" of fast-import). This ultimately means \nthat we cannot handle notes as \"regular\" trees and commits (which is \nwhat I'm trying to do with the help of this patch), and suggests that \ninstead of using 'commit' with 'M' for adding notes, we should probably \nhave a dedicated 'note' fast-import command that collects note objects, \nand does the tree transformation and subsequent commit upon \ncheckpoint/exit.\n\n\nHave fun! :)\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"118891","messageId":"20090727183517.GN11191@spearce.org","threadId":"20242","inReplyTo":"200907272026.46150.johan@herland.net","subject":"Re: [RFC 06/11] Add support for mark references as path names","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-07-27T18:35:17Z","receivedAt":"2009-07-27T18:35:17Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Johan Herland <johan@herland.net> wrote:\n> On Monday 27 July 2009, Shawn O. Pearce wrote:\n> > I think you need to find another back door, something that the\n> > language wouldn't have considered as valid previously.\n> \n> Ok. One (moderately hideous) option is to introduce new commands m/d/r/c \n> that works just like M/D/R/C, except that they also expand mark \n> references (leaving M/D/R/C with the old behaviour). I don't know how \n> you'd feel about that...\n\nBleh.  Because I think this has more truth to it:\n \n> However, I'm also pondering Dscho's idea of organizing note trees into \n> hierarchies (to limit #entries in tree objects), and (although I have \n> yet to try to implement this) it feels like this transformation should \n> be done in the notes.c code, which means that it must happen on \n> the \"git side\" of fast-import (at least the transformation should not \n> happen on the \"external side\" of fast-import). This ultimately means \n> that we cannot handle notes as \"regular\" trees and commits (which is \n> what I'm trying to do with the help of this patch), and suggests that \n> instead of using 'commit' with 'M' for adding notes, we should probably \n> have a dedicated 'note' fast-import command that collects note objects, \n> and does the tree transformation and subsequent commit upon \n> checkpoint/exit.\n\nExactly.  We probably want to do this instead.\n\nThough you might want the \"note\" command to be a subcommand of\ncommit, like M/D/R/C are, because notes are wrapped up inside of\na commit and you can modify multiple notes in a single commit.\n\n-- \nShawn.\n"},{"id":"118894","messageId":"7v1vo2j6qo.fsf@alter.siamese.dyndns.org","threadId":"20242","inReplyTo":"1248656659-21415-4-git-send-email-johan@herland.net","subject":"Re: [RFC 03/11] Allow programs to not depend on remotes having urls","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-27T18:55:27Z","receivedAt":"2009-07-27T18:55:27Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johan Herland <johan@herland.net> writes:\n\n> diff --git a/builtin-ls-remote.c b/builtin-ls-remote.c\n> index 78a88f7..4c6fc58 100644\n> --- a/builtin-ls-remote.c\n> +++ b/builtin-ls-remote.c\n> @@ -87,9 +87,9 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n>  \t\t}\n>  \t}\n>  \tremote = nongit ? NULL : remote_get(dest);\n> -\tif (remote && !remote->url_nr)\n> +\tif (!nongit && !remote)\n>  \t\tdie(\"remote %s has no configured URL\", dest);\n\nIt appears to me that remote_get() calls make_remote() that never returns\nNULL, thus this check will never trigger.  At least, the die() message\nneeds to be updated, since remote_get() may return NULL for some reason\nother than \"no configured URL\", but the condition the message says is not\nwhat this code checks.\n\nIt is Ok if the new world order is that the URL does not have to be known\nbefore transport_get() is called, but if that is the case, it should be\nmade clear by removing this check from here (and possibly having a new\ncheck elsewhere where it really matters, e.g. somewhere in transport\ncode).\n\n> -\ttransport = transport_get(remote, remote ? remote->url[0] : dest);\n> +\ttransport = transport_get(remote, remote ? NULL : dest);\n>  \tif (uploadpack != NULL)\n>  \t\ttransport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);\n"},{"id":"118895","messageId":"alpine.LNX.2.00.0907271412190.2147@iabervon.org","threadId":"20242","inReplyTo":"200907272011.19430.johan@herland.net","subject":"Re: [RFC 00/11] Foreign VCS helper program for CVS repositories","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2009-07-27T18:58:24Z","receivedAt":"2009-07-27T18:58:24Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Mon, 27 Jul 2009, Johan Herland wrote:\n\n> On Monday 27 July 2009, Daniel Barkalow wrote:\n> > On Mon, 27 Jul 2009, Johan Herland wrote:\n> > > This series is a first draft towards implementing a foreign VCS\n> > > helper program for CVS.\n> > >\n> > > It is based on the 'db/foreign-scm' and 'jh/notes' topics in 'pu'.\n> > > As such, this patch series should apply cleanly to current 'pu'.\n> > >\n> > > The first 4 patches supply the necessary parts of Daniel Barkalow's\n> > > foreign-scm topic that has not yet been merged to 'pu' (i.e.\n> > > everything remaining in Daniel's original patch series, except the\n> > > p4-specific stuff).\n> >\n> > I've got some changes to this series in the works; I just made a few\n> > changes to share the transport-side code for interacting with the\n> > helper with the transport-side code for interacting with\n> > native-object helpers. Mainly, this means starting each line in the\n> > \"list\" response with \"?\" to indicate that you don't know the hash,\n> > since the protocol is trying to be compatible with cases where you do\n> > know.\n> \n> No problem. I'm actually considering whether I should rewrite the CVS \n> helper to a full-fledged git-shim (btw, thanks for the shim work; it \n> looks really promising). I would still probably have to use \n> git-fast-import, but I would have more control over the fast-import \n> process (e.g. by closing the fast-import process myself, I could \n> simplify the code maintaining the marks database).\n> \n> With the git-shim feature already having found an excellent use case \n> (the HTTP fetcher), how do you see the future for the foreign-scm \n> topic? I like the idea of rewriting foreign-scm on top of git-shim, but \n> is there anything substantial _left_ in foreign-scm after such a \n> rewrite?\n\nThings that are still there:\n\n - vcs helpers make active use of the ability to state that there is a \n   remote ref by a particular name, without having any idea what hash it \n   currently holds (until they're told to import it).\n\n - vcs helper is specified directly by the user's config, possibly to \n   invoke a helper distributed separately; shim helpers are determined by \n   transport_get() when it identifies that the url can be handled by that \n   shim.\n\n - vcs helpers don't necessarily use URLs, or anything that works in the \n   same way, to identify the remote repo.\n\n - vcs export wants to deal with the remote server pretty much always \n   rewriting exported commits.\n\n - For export, the vcs helper is going to want to get the commits ordered \n   in some way that makes each export a single-commit export operation, so \n   that each helper doesn't have to deal with ordering the commits \n   suitably; this is particularly significant because the transport-side \n   code should make sure that the history is something that can be \n   represented in the foreign vcs. The native shim helper wants just the \n   endpoint.\n\n> > > Next, there are 3 patches tweaking and expanding the git-vcs API\n> > > (with corresponding implementations in the foreign transport code)\n> > > to adjust for the CVS helper's needs.\n> >\n> > These make sense to me. I assume you're planning to support exporting\n> > in some ways, but haven't got it working yet?\n> \n> Indeed. The current version is only a first draft that fetches \n> successfully from simple toy repositories (but probably not many \n> real-world CVS repos). I hope to support both fetching and pushing to \n> real-world CVS repos at some point.\n\nGreat.\n\t-Daniel\n*This .sig left intentionally blank*\n"},{"id":"118898","messageId":"alpine.LNX.2.00.0907271501300.2147@iabervon.org","threadId":"20242","inReplyTo":"7v1vo2j6qo.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC 03/11] Allow programs to not depend on remotes having urls","fromName":"Daniel Barkalow","fromEmail":"barkalow@iabervon.org","sentAt":"2009-07-27T19:33:32Z","receivedAt":"2009-07-27T19:33:32Z","isPatch":false,"sender":{"key":"barkalow@iabervon.org","avatar":"https://avatars.githubusercontent.com/u/55364219?v=4"},"body":"On Mon, 27 Jul 2009, Junio C Hamano wrote:\n\n> Johan Herland <johan@herland.net> writes:\n> \n> > diff --git a/builtin-ls-remote.c b/builtin-ls-remote.c\n> > index 78a88f7..4c6fc58 100644\n> > --- a/builtin-ls-remote.c\n> > +++ b/builtin-ls-remote.c\n> > @@ -87,9 +87,9 @@ int cmd_ls_remote(int argc, const char **argv, const char *prefix)\n> >  \t\t}\n> >  \t}\n> >  \tremote = nongit ? NULL : remote_get(dest);\n> > -\tif (remote && !remote->url_nr)\n> > +\tif (!nongit && !remote)\n> >  \t\tdie(\"remote %s has no configured URL\", dest);\n> \n> It appears to me that remote_get() calls make_remote() that never returns\n> NULL, thus this check will never trigger.  At least, the die() message\n> needs to be updated, since remote_get() may return NULL for some reason\n> other than \"no configured URL\", but the condition the message says is not\n> what this code checks.\n\nThe previous patch in the series causes remote_get() to return NULL if \nthe remote configuration is invalid. You're right, however, that the \nmessage should be something more directly accurate.\n\n> It is Ok if the new world order is that the URL does not have to be known\n> before transport_get() is called, but if that is the case, it should be\n> made clear by removing this check from here (and possibly having a new\n> check elsewhere where it really matters, e.g. somewhere in transport\n> code).\n\nThis spot is trying to make sure that the remote was valid, according to \nremote.c\n\n> > -\ttransport = transport_get(remote, remote ? remote->url[0] : dest);\n> > +\ttransport = transport_get(remote, remote ? NULL : dest);\n> >  \tif (uploadpack != NULL)\n> >  \t\ttransport_set_option(transport, TRANS_OPT_UPLOADPACK, uploadpack);\n> --\n> To unsubscribe from this list: send the line \"unsubscribe git\" in\n> the body of a message to majordomo@vger.kernel.org\n> More majordomo info at  http://vger.kernel.org/majordomo-info.html\n> \n"},{"id":"118914","messageId":"200907280343.56586.johan@herland.net","threadId":"20242","inReplyTo":"20090727183517.GN11191@spearce.org","subject":"[RFC 06/11 v2] fast-import: Add support for importing commit notes","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-28T01:43:56Z","receivedAt":"2009-07-28T01:43:56Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"Introduce a 'notemodify' subcommand of the 'commit' command. This subcommand\nis similar to 'filemodify', except that no mode is supplied (all notes have\nmode 0644), and the path is set to the hex SHA1 of the given \"comittish\".\n\nThis enables fast import of note objects along with their associated commits,\nsince the notes can now be named using the mark references of their\ncorresponding commits.\n\nThe patch also includes a test case of the added functionality.\n\nSigned-off-by: Johan Herland <johan@herland.net>\n---\n\nOn Monday 27 July 2009, Shawn O. Pearce wrote:\n> Though you might want the \"note\" command to be a subcommand of\n> commit, like M/D/R/C are, because notes are wrapped up inside of\n> a commit and you can modify multiple notes in a single commit.\n\nThanks for the suggestion. Here's a replacement patch introducing a new\n'notemodify' (\"N\") command.\n\nNote that this patch also makes the preceding patch superfluous:\n\n  [RFC 05/11] Refactor path name parsing into new function: get_path_str()\n\nIf you think that patch is useful in its own right, I can keep it in the\nseries, although it has no connection to the rest of the series at this\npoint.\n\nFinally, this patch should probably migrate into the jh/notes topic...\n\n\nHave fun! :)\n\n...Johan\n\n\n Documentation/git-fast-import.txt |   45 +++++++++--\n fast-import.c                     |   88 +++++++++++++++++++-\n t/t9300-fast-import.sh            |  166 +++++++++++++++++++++++++++++++++++++\n 3 files changed, 289 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex c2f483a..288032c 100644\n--- a/Documentation/git-fast-import.txt\n+++ b/Documentation/git-fast-import.txt\n@@ -316,7 +316,7 @@ change to the project.\n \tdata\n \t('from' SP <committish> LF)?\n \t('merge' SP <committish> LF)?\n-\t(filemodify | filedelete | filecopy | filerename | filedeleteall)*\n+\t(filemodify | filedelete | filecopy | filerename | filedeleteall | notemodify)*\n \tLF?\n ....\n \n@@ -339,14 +339,13 @@ commit message use a 0 length data.  Commit messages are free-form\n and are not interpreted by Git.  Currently they must be encoded in\n UTF-8, as fast-import does not permit other encodings to be specified.\n \n-Zero or more `filemodify`, `filedelete`, `filecopy`, `filerename`\n-and `filedeleteall` commands\n+Zero or more `filemodify`, `filedelete`, `filecopy`, `filerename`,\n+`filedeleteall` and `notemodify` commands\n may be included to update the contents of the branch prior to\n creating the commit.  These commands may be supplied in any order.\n However it is recommended that a `filedeleteall` command precede\n-all `filemodify`, `filecopy` and `filerename` commands in the same\n-commit, as `filedeleteall`\n-wipes the branch clean (see below).\n+all `filemodify`, `filecopy`, `filerename` and `notemodify` commands in\n+the same commit, as `filedeleteall` wipes the branch clean (see below).\n \n The `LF` after the command is optional (it used to be required).\n \n@@ -595,6 +594,40 @@ more memory per active branch (less than 1 MiB for even most large\n projects); so frontends that can easily obtain only the affected\n paths for a commit are encouraged to do so.\n \n+`notemodify`\n+^^^^^^^^^^^^\n+Included in a `commit` command to add a new note (annotating a given\n+commit) or change the content of an existing note.  This command has\n+two different means of specifying the content of the note.\n+\n+External data format::\n+\tThe data content for the note was already supplied by a prior\n+\t`blob` command.  The frontend just needs to connect it to the\n+\tcommit that is to be annotated.\n++\n+....\n+\t'N' SP <dataref> SP <committish> LF\n+....\n++\n+Here `<dataref>` can be either a mark reference (`:<idnum>`)\n+set by a prior `blob` command, or a full 40-byte SHA-1 of an\n+existing Git blob object.\n+\n+Inline data format::\n+\tThe data content for the note has not been supplied yet.\n+\tThe frontend wants to supply it as part of this modify\n+\tcommand.\n++\n+....\n+\t'N' SP 'inline' SP <committish> LF\n+\tdata\n+....\n++\n+See below for a detailed description of the `data` command.\n+\n+In both formats `<committish>` is any of the commit specification\n+expressions also accepted by `from` (see above).\n+\n `mark`\n ~~~~~~\n Arranges for fast-import to save a reference to the current object, allowing\ndiff --git a/fast-import.c b/fast-import.c\nindex 8a7cdc1..a366c61 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -22,8 +22,8 @@ Format of STDIN stream:\n     ('author' sp name sp '<' email '>' sp when lf)?\n     'committer' sp name sp '<' email '>' sp when lf\n     commit_msg\n-    ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?\n-    ('merge' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)*\n+    ('from' sp committish lf)?\n+    ('merge' sp committish lf)*\n     file_change*\n     lf?;\n   commit_msg ::= data;\n@@ -41,15 +41,18 @@ Format of STDIN stream:\n   file_obm ::= 'M' sp mode sp (hexsha1 | idnum) sp path_str lf;\n   file_inm ::= 'M' sp mode sp 'inline' sp path_str lf\n     data;\n+  note_obm ::= 'N' sp (hexsha1 | idnum) sp committish lf;\n+  note_inm ::= 'N' sp 'inline' sp committish lf\n+    data;\n \n   new_tag ::= 'tag' sp tag_str lf\n-    'from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf\n+    'from' sp committish lf\n     ('tagger' sp name sp '<' email '>' sp when lf)?\n     tag_msg;\n   tag_msg ::= data;\n \n   reset_branch ::= 'reset' sp ref_str lf\n-    ('from' sp (ref_str | hexsha1 | sha1exp_str | idnum) lf)?\n+    ('from' sp committish lf)?\n     lf?;\n \n   checkpoint ::= 'checkpoint' lf\n@@ -88,6 +91,7 @@ Format of STDIN stream:\n      # stream formatting is: \\, \" and LF.  Otherwise these values\n      # are UTF8.\n      #\n+  committish  ::= (ref_str | hexsha1 | sha1exp_str | idnum);\n   ref_str     ::= ref;\n   sha1exp_str ::= sha1exp;\n   tag_str     ::= tag;\n@@ -2007,6 +2011,80 @@ static void file_change_cr(struct branch *b, int rename)\n \t\tleaf.tree);\n }\n \n+static void note_change_n(struct branch *b)\n+{\n+\tconst char *p = command_buf.buf + 2;\n+\tstatic struct strbuf uq = STRBUF_INIT;\n+\tstruct object_entry *oe = oe;\n+\tstruct branch *s;\n+\tunsigned char sha1[20], commit_sha1[20];\n+\tuint16_t inline_data = 0;\n+\n+\t/* <dataref> or 'inline' */\n+\tif (*p == ':') {\n+\t\tchar *x;\n+\t\toe = find_mark(strtoumax(p + 1, &x, 10));\n+\t\thashcpy(sha1, oe->sha1);\n+\t\tp = x;\n+\t} else if (!prefixcmp(p, \"inline\")) {\n+\t\tinline_data = 1;\n+\t\tp += 6;\n+\t} else {\n+\t\tif (get_sha1_hex(p, sha1))\n+\t\t\tdie(\"Invalid SHA1: %s\", command_buf.buf);\n+\t\toe = find_object(sha1);\n+\t\tp += 40;\n+\t}\n+\tif (*p++ != ' ')\n+\t\tdie(\"Missing space after SHA1: %s\", command_buf.buf);\n+\n+\t/* <committish> */\n+\ts = lookup_branch(p);\n+\tif (s) {\n+\t\thashcpy(commit_sha1, s->sha1);\n+\t} else if (*p == ':') {\n+\t\tuintmax_t commit_mark = strtoumax(p + 1, NULL, 10);\n+\t\tstruct object_entry *commit_oe = find_mark(commit_mark);\n+\t\tif (commit_oe->type != OBJ_COMMIT)\n+\t\t\tdie(\"Mark :%\" PRIuMAX \" not a commit\", commit_mark);\n+\t\thashcpy(commit_sha1, commit_oe->sha1);\n+\t} else if (!get_sha1(p, commit_sha1)) {\n+\t\tunsigned long size;\n+\t\tchar *buf = read_object_with_reference(commit_sha1,\n+\t\t\tcommit_type, &size, commit_sha1);\n+\t\tif (!buf || size < 46)\n+\t\t\tdie(\"Not a valid commit: %s\", p);\n+\t\tfree(buf);\n+\t} else\n+\t\tdie(\"Invalid ref name or SHA1 expression: %s\", p);\n+\n+\tif (inline_data) {\n+\t\tstatic struct strbuf buf = STRBUF_INIT;\n+\n+\t\tif (p != uq.buf) {\n+\t\t\tstrbuf_addstr(&uq, p);\n+\t\t\tp = uq.buf;\n+\t\t}\n+\t\tread_next_command();\n+\t\tparse_data(&buf);\n+\t\tstore_object(OBJ_BLOB, &buf, &last_blob, sha1, 0);\n+\t} else if (oe) {\n+\t\tif (oe->type != OBJ_BLOB)\n+\t\t\tdie(\"Not a blob (actually a %s): %s\",\n+\t\t\t\ttypename(oe->type), command_buf.buf);\n+\t} else {\n+\t\tenum object_type type = sha1_object_info(sha1, NULL);\n+\t\tif (type < 0)\n+\t\t\tdie(\"Blob not found: %s\", command_buf.buf);\n+\t\tif (type != OBJ_BLOB)\n+\t\t\tdie(\"Not a blob (actually a %s): %s\",\n+\t\t\t    typename(type), command_buf.buf);\n+\t}\n+\n+\ttree_content_set(&b->branch_tree, sha1_to_hex(commit_sha1), sha1,\n+\t\tS_IFREG | 0644, NULL);\n+}\n+\n static void file_change_deleteall(struct branch *b)\n {\n \trelease_tree_content_recursive(b->branch_tree.tree);\n@@ -2176,6 +2254,8 @@ static void parse_new_commit(void)\n \t\t\tfile_change_cr(b, 1);\n \t\telse if (!prefixcmp(command_buf.buf, \"C \"))\n \t\t\tfile_change_cr(b, 0);\n+\t\telse if (!prefixcmp(command_buf.buf, \"N \"))\n+\t\t\tnote_change_n(b);\n \t\telse if (!strcmp(\"deleteall\", command_buf.buf))\n \t\t\tfile_change_deleteall(b);\n \t\telse {\ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex 821be7c..b49815d 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -1088,4 +1088,170 @@ INPUT_END\n test_expect_success 'P: fail on blob mark in gitlink' '\n     test_must_fail git fast-import <input'\n \n+###\n+### series Q (notes)\n+###\n+\n+note1_data=\"Note for the first commit\"\n+note2_data=\"Note for the second commit\"\n+note3_data=\"Note for the third commit\"\n+\n+test_tick\n+cat >input <<INPUT_END\n+blob\n+mark :2\n+data <<EOF\n+$file2_data\n+EOF\n+\n+commit refs/heads/notes-test\n+mark :3\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+data <<COMMIT\n+first (:3)\n+COMMIT\n+\n+M 644 :2 file2\n+\n+blob\n+mark :4\n+data $file4_len\n+$file4_data\n+commit refs/heads/notes-test\n+mark :5\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+data <<COMMIT\n+second (:5)\n+COMMIT\n+\n+M 644 :4 file4\n+\n+commit refs/heads/notes-test\n+mark :6\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+data <<COMMIT\n+third (:6)\n+COMMIT\n+\n+M 644 inline file5\n+data <<EOF\n+$file5_data\n+EOF\n+\n+M 755 inline file6\n+data <<EOF\n+$file6_data\n+EOF\n+\n+blob\n+mark :7\n+data <<EOF\n+$note1_data\n+EOF\n+\n+blob\n+mark :8\n+data <<EOF\n+$note2_data\n+EOF\n+\n+commit refs/notes/foobar\n+mark :9\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+data <<COMMIT\n+notes (:9)\n+COMMIT\n+\n+N :7 :3\n+N :8 :5\n+N inline :6\n+data <<EOF\n+$note3_data\n+EOF\n+\n+INPUT_END\n+test_expect_success \\\n+\t'Q: commit notes' \\\n+\t'git fast-import <input &&\n+\t git whatchanged notes-test'\n+test_expect_success \\\n+\t'Q: verify pack' \\\n+\t'for p in .git/objects/pack/*.pack;do git verify-pack $p||exit;done'\n+\n+commit1=$(git rev-parse notes-test~2)\n+commit2=$(git rev-parse notes-test^)\n+commit3=$(git rev-parse notes-test)\n+\n+cat >expect <<EOF\n+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+\n+first (:3)\n+EOF\n+test_expect_success \\\n+\t'Q: verify first commit' \\\n+\t'git cat-file commit notes-test~2 | sed 1d >actual &&\n+\ttest_cmp expect actual'\n+\n+cat >expect <<EOF\n+parent $commit1\n+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+\n+second (:5)\n+EOF\n+test_expect_success \\\n+\t'Q: verify second commit' \\\n+\t'git cat-file commit notes-test^ | sed 1d >actual &&\n+\ttest_cmp expect actual'\n+\n+cat >expect <<EOF\n+parent $commit2\n+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+\n+third (:6)\n+EOF\n+test_expect_success \\\n+\t'Q: verify third commit' \\\n+\t'git cat-file commit notes-test | sed 1d >actual &&\n+\ttest_cmp expect actual'\n+\n+cat >expect <<EOF\n+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE\n+\n+notes (:9)\n+EOF\n+test_expect_success \\\n+\t'Q: verify notes commit' \\\n+\t'git cat-file commit refs/notes/foobar | sed 1d >actual &&\n+\ttest_cmp expect actual'\n+\n+cat >expect.unsorted <<EOF\n+100644 blob $commit1\n+100644 blob $commit2\n+100644 blob $commit3\n+EOF\n+cat expect.unsorted | sort >expect\n+test_expect_success \\\n+\t'Q: verify notes tree' \\\n+\t'git cat-file -p refs/notes/foobar^{tree} | sed \"s/ [0-9a-f]*\t/ /\" >actual &&\n+\t test_cmp expect actual'\n+\n+echo \"$note1_data\" >expect\n+test_expect_success \\\n+\t'Q: verify note for first commit' \\\n+\t'git cat-file blob refs/notes/foobar:$commit1 >actual && test_cmp expect actual'\n+\n+echo \"$note2_data\" >expect\n+test_expect_success \\\n+\t'Q: verify note for second commit' \\\n+\t'git cat-file blob refs/notes/foobar:$commit2 >actual && test_cmp expect actual'\n+\n+echo \"$note3_data\" >expect\n+test_expect_success \\\n+\t'Q: verify note for third commit' \\\n+\t'git cat-file blob refs/notes/foobar:$commit3 >actual && test_cmp expect actual'\n+\n test_done\n-- \n1.6.4.rc3.138.ga6b98.dirty\n"},{"id":"119003","messageId":"7vskgg1bbt.fsf@alter.siamese.dyndns.org","threadId":"20242","inReplyTo":"200907280343.56586.johan@herland.net","subject":"Re: [RFC 06/11 v2] fast-import: Add support for importing commit notes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-29T02:18:14Z","receivedAt":"2009-07-29T02:18:14Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johan Herland <johan@herland.net> writes:\n\n> +External data format::\n> +\tThe data content for the note was already supplied by a prior\n> +\t`blob` command.  The frontend just needs to connect it to the\n> +\tcommit that is to be annotated.\n> ++\n> +....\n> +\t'N' SP <dataref> SP <committish> LF\n> +....\n> ++\n> +Here `<dataref>` can be either a mark reference (`:<idnum>`)\n> +set by a prior `blob` command, or a full 40-byte SHA-1 of an\n> +existing Git blob object.\n> +\n> +Inline data format::\n> +\tThe data content for the note has not been supplied yet.\n> +\tThe frontend wants to supply it as part of this modify\n> +\tcommand.\n> ++\n> +....\n> +\t'N' SP 'inline' SP <committish> LF\n> +\tdata\n> +....\n> ++\n> +See below for a detailed description of the `data` command.\n> +\n> +In both formats `<committish>` is any of the commit specification\n> +expressions also accepted by `from` (see above).\n\nDoesn't this make fast-import language incapable of add notes to anything\nother than commits?  As far as I remember, there is no such limitation in\nthe underlying data structure on git notes, even though the git-notes\nsample Porcelain might have such a restriction.\n\nWe recently hit a similar unintended limitation that we regret in the\nfast-import language, didn't we?\n\nAlthough personally I do not think it is a big deal if we cannot tag or\nadd notes to trees, I am pointing it out in case other people care.\n"},{"id":"119013","messageId":"200907290441.08246.johan@herland.net","threadId":"20242","inReplyTo":"7vskgg1bbt.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC 06/11 v2] fast-import: Add support for importing commit notes","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-29T02:41:07Z","receivedAt":"2009-07-29T02:41:07Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Wednesday 29 July 2009, Junio C Hamano wrote:\n> Johan Herland <johan@herland.net> writes:\n> > +External data format::\n> > +\tThe data content for the note was already supplied by a prior\n> > +\t`blob` command.  The frontend just needs to connect it to the\n> > +\tcommit that is to be annotated.\n> > ++\n> > +....\n> > +\t'N' SP <dataref> SP <committish> LF\n> > +....\n> > ++\n> > +Here `<dataref>` can be either a mark reference (`:<idnum>`)\n> > +set by a prior `blob` command, or a full 40-byte SHA-1 of an\n> > +existing Git blob object.\n> > +\n> > +Inline data format::\n> > +\tThe data content for the note has not been supplied yet.\n> > +\tThe frontend wants to supply it as part of this modify\n> > +\tcommand.\n> > ++\n> > +....\n> > +\t'N' SP 'inline' SP <committish> LF\n> > +\tdata\n> > +....\n> > ++\n> > +See below for a detailed description of the `data` command.\n> > +\n> > +In both formats `<committish>` is any of the commit specification\n> > +expressions also accepted by `from` (see above).\n>\n> Doesn't this make fast-import language incapable of add notes to anything\n> other than commits?  As far as I remember, there is no such limitation in\n> the underlying data structure on git notes, even though the git-notes\n> sample Porcelain might have such a restriction.\n\nIt does (probably because the default notes tree is \"refs/notes/commits\").\n\n> We recently hit a similar unintended limitation that we regret in the\n> fast-import language, didn't we?\n\nI don't know. Must have slipped past my mailbox.\n\n> Although personally I do not think it is a big deal if we cannot tag or\n> add notes to trees, I am pointing it out in case other people care.\n\nI copied the semantics from the 'tag' command, for no particular reason \n(except following the git-notes procelain). Expanding 'notemodify' (and \n'tag') to cover all types of objects is fine by me, unless there are good \narguments otherwise. Shawn?\n\n\nHave fun!\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"119041","messageId":"81b0412b0907290157y56255296qd3374f22ec3c7883@mail.gmail.com","threadId":"20242","inReplyTo":"1248656659-21415-4-git-send-email-johan@herland.net","subject":"Re: [RFC 03/11] Allow programs to not depend on remotes having urls","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2009-07-29T08:57:37Z","receivedAt":"2009-07-29T08:57:37Z","isPatch":false,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"On Mon, Jul 27, 2009 at 03:04, Johan Herland<johan@herland.net> wrote:\n> diff --git a/builtin-fetch.c b/builtin-fetch.c\n> index 817dd6b..3f32db6 100644\n> --- a/builtin-fetch.c\n> +++ b/builtin-fetch.c\n> @@ -346,12 +346,17 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,\n> +               if (url) {\n> +                       url_len = strlen(url);\n> +                       for (i = url_len - 1; url[i] == '/' && 0 <= i; i--)\n> +                               ;\n> +                       url_len = i + 1;\n> +                       if (4 < i && !strncmp(\".git\", url + i - 3, 4))\n> +                               url_len = i - 3;\n> +               } else {\n> +                       url = \"foriegn\";\n\nTypo. Should be \"foreign\".\n"},{"id":"119064","messageId":"20090729142634.GC1033@spearce.org","threadId":"20242","inReplyTo":"200907290441.08246.johan@herland.net","subject":"Re: [RFC 06/11 v2] fast-import: Add support for importing commit notes","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2009-07-29T14:26:34Z","receivedAt":"2009-07-29T14:26:34Z","isPatch":false,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Johan Herland <johan@herland.net> wrote:\n> On Wednesday 29 July 2009, Junio C Hamano wrote:\n> > Johan Herland <johan@herland.net> writes:\n> > > +\n> > > +In both formats `<committish>` is any of the commit specification\n> > > +expressions also accepted by `from` (see above).\n> >\n> > Doesn't this make fast-import language incapable of add notes to anything\n> > other than commits?  As far as I remember, there is no such limitation in\n> > the underlying data structure on git notes, even though the git-notes\n> > sample Porcelain might have such a restriction.\n> \n> It does (probably because the default notes tree is \"refs/notes/commits\").\n\nYea, it does have that limitation right now.  That limitation could\nbe relaxed in the code by just allowing the <committish> to be any\nobject and simply don't check its type.\n\nBut I've already stated with regards to the notes that I think we\nshould only allow noting commits and annotated tags, where we have\na timestamp we can use to split the notes in the note tree by time,\nso that we can index recent notes much more quickly and can answer\n`git log -20` much more efficiently.\n\nI just don't see a lot of value in noting a blob or a tree, there\nis too little context information on such things for it to really\nbe all that useful.\n\n> > We recently hit a similar unintended limitation that we regret in the\n> > fast-import language, didn't we?\n> \n> I don't know. Must have slipped past my mailbox.\n\nI remember something being raised, but I can't remember exactly\nwhat it was either.\n\nIt might have had to do with the effects of rename commands, e.g. a\nfile rename takes place immediately when issued, and some frontends\nwanted it to take place only after the commit was completed.\n \n> > Although personally I do not think it is a big deal if we cannot tag or\n> > add notes to trees, I am pointing it out in case other people care.\n> \n> I copied the semantics from the 'tag' command, for no particular reason \n> (except following the git-notes procelain). Expanding 'notemodify' (and \n> 'tag') to cover all types of objects is fine by me, unless there are good \n> arguments otherwise. Shawn?\n\ntag, there might be arguments for tagging trees, e.g. so you can\nexport the linux kernel repository with `git fast-export` and reload\nit with fast-import.  But that's unrelated to this change.\n\nSee above about notes.\n\n-- \nShawn.\n"},{"id":"119076","messageId":"7v8wi7wjex.fsf@alter.siamese.dyndns.org","threadId":"20242","inReplyTo":"20090729142634.GC1033@spearce.org","subject":"Re: [RFC 06/11 v2] fast-import: Add support for importing commit notes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-29T16:20:06Z","receivedAt":"2009-07-29T16:20:06Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"\"Shawn O. Pearce\" <spearce@spearce.org> writes:\n\n>> > We recently hit a similar unintended limitation that we regret in the\n>> > fast-import language, didn't we?\n>> \n>> I don't know. Must have slipped past my mailbox.\n>\n> I remember something being raised, but I can't remember exactly\n> what it was either.\n\nExporting a tag that points at a non commit was what I had in mind.\n\n> tag, there might be arguments for tagging trees, e.g. so you can\n> export the linux kernel repository with `git fast-export` and reload\n> it with fast-import.  But that's unrelated to this change.\n>\n> See above about notes.\n\nI think we are in agreement then.  Good.\n"},{"id":"119090","messageId":"7v1vnzuxly.fsf@alter.siamese.dyndns.org","threadId":"20242","inReplyTo":"200907280343.56586.johan@herland.net","subject":"Re: [RFC 06/11 v2] fast-import: Add support for importing commit notes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-29T18:56:25Z","receivedAt":"2009-07-29T18:56:25Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johan Herland <johan@herland.net> writes:\n\n> Introduce a 'notemodify' subcommand of the 'commit' command. This subcommand\n> is similar to 'filemodify', except that no mode is supplied (all notes have\n> mode 0644), and the path is set to the hex SHA1 of the given \"comittish\".\n>\n> This enables fast import of note objects along with their associated commits,\n> since the notes can now be named using the mark references of their\n> corresponding commits.\n>\n> The patch also includes a test case of the added functionality.\n>\n> Signed-off-by: Johan Herland <johan@herland.net>\n\nThanks.\n\nReplacing this will cascade to the rest of the series, right?\n"},{"id":"119118","messageId":"200907300108.51703.johan@herland.net","threadId":"20242","inReplyTo":"7v1vnzuxly.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC 06/11 v2] fast-import: Add support for importing commit notes","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-29T23:08:51Z","receivedAt":"2009-07-29T23:08:51Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Wednesday 29 July 2009, Junio C Hamano wrote:\n> Johan Herland <johan@herland.net> writes:\n> > Introduce a 'notemodify' subcommand of the 'commit' command. This\n> > subcommand is similar to 'filemodify', except that no mode is supplied\n> > (all notes have mode 0644), and the path is set to the hex SHA1 of the\n> > given \"comittish\".\n> >\n> > This enables fast import of note objects along with their associated\n> > commits, since the notes can now be named using the mark references of\n> > their corresponding commits.\n> >\n> > The patch also includes a test case of the added functionality.\n> >\n> > Signed-off-by: Johan Herland <johan@herland.net>\n>\n> Thanks.\n>\n> Replacing this will cascade to the rest of the series, right?\n\nNot sure what you mean by \"cascade to the rest of the series\". If you just \nreplace 06/11_v1 with 06/11_v2, things will stop working (since 10/11 and \n11/11 needs a corresponding update of their fast-import commands).\n\nOn the other hand, I have moved this patch into the jh/notes series (which I \nupdated/resent last night).\n\nI will update/resend this patch series tomorrow, with suggested fixes, and \nrebased onto the updated jh/notes series.\n\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"119131","messageId":"200907300224.33244.johan@herland.net","threadId":"20242","inReplyTo":"81b0412b0907290157y56255296qd3374f22ec3c7883@mail.gmail.com","subject":"Re: [RFC 03/11] Allow programs to not depend on remotes having urls","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-30T00:24:33Z","receivedAt":"2009-07-30T00:24:33Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Wednesday 29 July 2009, Alex Riesen wrote:\n> On Mon, Jul 27, 2009 at 03:04, Johan Herland<johan@herland.net> wrote:\n> > diff --git a/builtin-fetch.c b/builtin-fetch.c\n> > index 817dd6b..3f32db6 100644\n> > --- a/builtin-fetch.c\n> > +++ b/builtin-fetch.c\n> > @@ -346,12 +346,17 @@ static int store_updated_refs(const char\n> > *raw_url, const char *remote_name, +               if (url) {\n> > +                       url_len = strlen(url);\n> > +                       for (i = url_len - 1; url[i] == '/' && 0 <= i;\n> > i--) +                               ;\n> > +                       url_len = i + 1;\n> > +                       if (4 < i && !strncmp(\".git\", url + i - 3, 4))\n> > +                               url_len = i - 3;\n> > +               } else {\n> > +                       url = \"foriegn\";\n>\n> Typo. Should be \"foreign\".\n\nThanks. Will be fixed in the next iteration of this topic.\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"119132","messageId":"200907300229.13642.johan@herland.net","threadId":"20242","inReplyTo":"7v8wi7wjex.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC 06/11 v2] fast-import: Add support for importing commit notes","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2009-07-30T00:29:13Z","receivedAt":"2009-07-30T00:29:13Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"On Wednesday 29 July 2009, Junio C Hamano wrote:\n> \"Shawn O. Pearce\" <spearce@spearce.org> writes:\n> >> > We recently hit a similar unintended limitation that we regret in\n> >> > the fast-import language, didn't we?\n> >>\n> >> I don't know. Must have slipped past my mailbox.\n> >\n> > I remember something being raised, but I can't remember exactly\n> > what it was either.\n>\n> Exporting a tag that points at a non commit was what I had in mind.\n>\n> > tag, there might be arguments for tagging trees, e.g. so you can\n> > export the linux kernel repository with `git fast-export` and reload\n> > it with fast-import.  But that's unrelated to this change.\n> >\n> > See above about notes.\n>\n> I think we are in agreement then.  Good.\n\nWe do? on what? That 'notemodify' should work on <committish> + <tag \nobject>? Or that 'notemodify' should work on <any object>?\n\n...Johan\n\n-- \nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"119146","messageId":"7veiryoq3b.fsf@alter.siamese.dyndns.org","threadId":"20242","inReplyTo":"200907300229.13642.johan@herland.net","subject":"Re: [RFC 06/11 v2] fast-import: Add support for importing commit notes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-07-30T02:35:20Z","receivedAt":"2009-07-30T02:35:20Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johan Herland <johan@herland.net> writes:\n\n> On Wednesday 29 July 2009, Junio C Hamano wrote:\n>> \"Shawn O. Pearce\" <spearce@spearce.org> writes:\n> ...\n>> > See above about notes.\n>>\n>> I think we are in agreement then.  Good.\n>\n> We do? on what?\n\nWe might mind if fast-import does not handle tags to non-commits, but we\nwould want to restrict notes to apply only to commits for other reasons\nanyway, and it is perfectly fine if your patch handled only notes that are\nattached to commits and not arbitrary objects.\n"}]}