git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
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

  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).