From: David Barr <david.barr@cordelta.com>
To: Git Mailing List <git@vger.kernel.org>
Cc: Ramkumar Ramachandra <artagnon@gmail.com>,
Sverre Rabbelier <srabbelier@gmail.com>,
"Shawn O. Pearce" <spearce@spearce.org>,
David Barr <david.barr@cordelta.com>
Subject: [PATCH] fast-import: add 'ls' command
Date: Thu, 2 Dec 2010 21:40:20 +1100 [thread overview]
Message-ID: <1291286420-13591-2-git-send-email-david.barr@cordelta.com> (raw)
In-Reply-To: <1291286420-13591-1-git-send-email-david.barr@cordelta.com>
There are two forms of the 'ls' command, one that takes a tree-ish and
one relative to the index. Allow the tree-ish variant to be used anywhere
a comment is allowed. Allow the index variant to be used within a commit
where file change commands would be used.
The syntax is as such:
'ls' SP <dataref> SP path LF
and
'ls' SP 'index' SP path LF
Based-on-patch-by: Jonathan Nieder <jrnieder@gmail.com>
Signed-off-by: David Barr <david.barr@cordelta.com>
---
fast-import.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 125 insertions(+), 2 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index fbc70cd..854398a 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -24,10 +24,12 @@ Format of STDIN stream:
commit_msg
('from' sp committish lf)?
('merge' sp committish lf)*
- file_change*
+ (file_change | ls)*
lf?;
commit_msg ::= data;
+ ls ::= 'ls' sp 'index' sp path_str lf;
+
file_change ::= file_clr
| file_del
| file_rnm
@@ -132,7 +134,7 @@ Format of STDIN stream:
ts ::= # time since the epoch in seconds, ascii base10 notation;
tz ::= # GIT style timezone;
- # note: comments and cat requests may appear anywhere
+ # note: comments, ls and cat requests may appear anywhere
# in the input, except within a data command. Any form
# of the data command always escapes the related input
# from comment processing.
@@ -141,7 +143,9 @@ Format of STDIN stream:
# must be the first character on that line (an lf
# preceded it).
#
+
cat_blob ::= 'cat-blob' sp (hexsha1 | idnum) lf;
+ ls_tree ::= 'ls' sp (hexsha1 | idnum) sp path_str lf;
comment ::= '#' not_lf* lf;
not_lf ::= # Any byte that is not ASCII newline (LF);
@@ -369,6 +373,7 @@ static int cat_blob_fd = STDOUT_FILENO;
static void parse_argv(void);
static void parse_cat_blob(void);
+static void parse_ls(struct branch *b);
/* Signal handling */
static volatile sig_atomic_t checkpoint_requested;
@@ -2607,6 +2612,8 @@ static void parse_new_commit(void)
note_change_n(b, prev_fanout);
else if (!strcmp("deleteall", command_buf.buf))
file_change_deleteall(b);
+ else if (!prefixcmp(command_buf.buf, "ls "))
+ parse_ls(b);
else {
unread_command_buf = 1;
break;
@@ -2830,6 +2837,120 @@ static void parse_cat_blob(void)
cat_blob(oe, sha1);
}
+static struct object_entry *parse_treeish_dataref(const char** r)
+{
+ unsigned char sha1[20];
+ struct object_entry *e;
+
+ if (**r == ':') {
+ char *x;
+ e = find_mark(strtoumax(*r + 1, &x, 10));
+ if (x == *r + 1)
+ die("Invalid mark: %s", command_buf.buf);
+ if (!e)
+ die("Unknown mark: %s", command_buf.buf);
+ *r = x;
+ hashcpy(sha1, e->idx.sha1);
+ } else {
+ if (get_sha1_hex(*r, sha1))
+ die("Invalid SHA1: %s", command_buf.buf);
+ e = find_object(sha1);
+ *r += 40;
+ }
+
+ for (;;) {
+ unsigned long size;
+ void *buf;
+ if (!e) {
+ enum object_type type = sha1_object_info(sha1, NULL);
+ if (type < 0)
+ die("object not found: %s", sha1_to_hex(sha1));
+ e = insert_object(sha1);
+ e->type = type;
+ e->pack_id = MAX_PACK_ID;
+ e->idx.offset = 1;
+ }
+ if (e->type == OBJ_TREE)
+ break;
+
+ if (e->type != OBJ_COMMIT && e->type != OBJ_TAG)
+ die("Not a treeish: %s", command_buf.buf);
+
+ if (e->pack_id != MAX_PACK_ID) {
+ buf = gfi_unpack_entry(e, &size);
+ } else {
+ enum object_type type;
+ buf = read_sha1_file(sha1, &type, &size);
+ }
+ if (!buf)
+ die("Can't load object %s", sha1_to_hex(sha1));
+
+ if (e->type == OBJ_COMMIT) {
+ if (size < 40 + strlen("tree ") ||
+ get_sha1_hex(buf + strlen("tree "), sha1))
+ die("Invalid SHA1 in commit: %s", command_buf.buf);
+ } else {
+ if (size < 40 + strlen("object ") ||
+ get_sha1_hex(buf + strlen("object "), sha1))
+ die("Invalid SHA1 in tag: %s", command_buf.buf);
+ }
+ free(buf);
+ e = find_object(sha1);
+ }
+
+ return e;
+}
+
+static void print_ls(int mode, unsigned char *sha1, char *path)
+{
+ enum object_type type;
+ struct strbuf line = STRBUF_INIT;
+ type = sha1_object_info(sha1, NULL);
+ /* mode SP type SP object_name TAB path LF */
+ strbuf_addf(&line, "%o %s %s\t%s\n",
+ mode, typename(type), sha1_to_hex(sha1), path);
+ cat_blob_write(line.buf, line.len);
+ strbuf_release(&line);
+}
+
+static void parse_ls(struct branch *b)
+{
+ const char *p;
+ struct strbuf uq = STRBUF_INIT;
+ struct tree_entry *root = NULL;
+ struct tree_entry leaf = {0};
+
+ /* ls SP <treeish> SP <path> */
+ p = command_buf.buf + strlen("ls ");
+ if(!prefixcmp(p, "index")) {
+ p += strlen("index");
+ if (!b)
+ die("Not in a commit: %s", command_buf.buf);
+ root = &b->branch_tree;
+ } else {
+ struct object_entry *e = parse_treeish_dataref(&p);
+ root = new_tree_entry();
+ hashcpy(root->versions[1].sha1, e->idx.sha1);
+ load_tree(root);
+ }
+ if (*p++ != ' ')
+ die("Missing space after SHA1: %s", command_buf.buf);
+ if (unquote_c_style(&uq, p, &p))
+ die("Invalid path: %s", command_buf.buf);
+ if (*p)
+ die("Garbage after path: %s", command_buf.buf);
+ tree_content_get(root, uq.buf, &leaf);
+ if (!leaf.versions[1].mode)
+ die("Path %s not in branch", uq.buf);
+ /* Allow new trees to be listed. */
+ if (S_ISDIR(leaf.versions[1].mode))
+ store_tree(&leaf);
+ print_ls(leaf.versions[1].mode, leaf.versions[1].sha1, uq.buf);
+ strbuf_release(&uq);
+ if (!b || root != &b->branch_tree)
+ release_tree_entry(root);
+}
+
static void checkpoint(void)
{
checkpoint_requested = 0;
@@ -3128,6 +3249,8 @@ int main(int argc, const char **argv)
while (read_next_command() != EOF) {
if (!strcmp("blob", command_buf.buf))
parse_new_blob();
+ else if (!prefixcmp(command_buf.buf, "ls "))
+ parse_ls(NULL);
else if (!prefixcmp(command_buf.buf, "commit "))
parse_new_commit();
else if (!prefixcmp(command_buf.buf, "tag "))
--
1.7.3
next prev parent reply other threads:[~2010-12-02 12:46 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-02 10:40 [PATCH/RFC] fast-import: add 'ls' command David Barr
2010-12-02 10:40 ` David Barr [this message]
2010-12-02 12:37 ` [PATCH] " Sverre Rabbelier
2010-12-02 12:57 ` David Michael Barr
2010-12-02 17:37 ` Jonathan Nieder
2010-12-02 19:20 ` Junio C Hamano
2010-12-02 22:51 ` David Barr
2011-01-03 8:01 ` [PATCH/RFC v2 0/3] " Jonathan Nieder
2011-01-03 8:22 ` [PATCH 1/3] fast-import: clarify handling of cat-blob feature Jonathan Nieder
2011-01-03 8:24 ` [PATCH 2/3] fast-import: treat filemodify with empty tree as delete Jonathan Nieder
2011-01-26 22:41 ` [PATCH v2] " Jonathan Nieder
2011-01-26 22:45 ` Sverre Rabbelier
2011-01-26 23:06 ` [PATCH jn/fast-import-fix v3] " Jonathan Nieder
2011-01-27 0:04 ` Junio C Hamano
2011-01-27 0:26 ` Jonathan Nieder
2011-01-27 6:07 ` [PATCH v4] " Jonathan Nieder
2011-01-27 19:33 ` Peter Baumann
2011-01-27 19:48 ` Jonathan Nieder
2011-01-27 20:46 ` Peter Baumann
2011-01-27 20:48 ` Peter Baumann
2011-01-28 17:13 ` Jonathan Nieder
2011-01-03 8:37 ` [PATCH 3/3] fast-import: add 'ls' command Jonathan Nieder
2011-01-26 21:39 ` [RFC] fast-import: 'cat-blob' and 'ls' commands Jonathan Nieder
2011-01-26 23:46 ` Sam Vilain
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1291286420-13591-2-git-send-email-david.barr@cordelta.com \
--to=david.barr@cordelta.com \
--cc=artagnon@gmail.com \
--cc=git@vger.kernel.org \
--cc=spearce@spearce.org \
--cc=srabbelier@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).