git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Nguyễn Thái Ngọc Duy" <pclouds@gmail.com>
To: git@vger.kernel.org
Subject: [PATCH 03/12] Introduce sparse prefix
Date: Wed, 23 Jul 2008 21:56:03 +0700	[thread overview]
Message-ID: <20080723145603.GA29079@laptop> (raw)

Sparse prefix is actually a list of prefixes separated by colons,
that will limit worktree usage within it.

This patch adds core.sparsecheckout and
"git rev-parse --show-sparse-prefix". This also adds manipulation
functions that will get used later.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin-rev-parse.c |    4 +
 cache.h             |   13 +++
 config.c            |    7 ++
 environment.c       |  221 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 245 insertions(+), 0 deletions(-)

diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index aa71f4a..4200f14 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -499,6 +499,10 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 					puts(prefix);
 				continue;
 			}
+			if (!strcmp(arg, "--show-sparse-prefix")) {
+				puts(get_sparse_prefix_str());
+				continue;
+			}
 			if (!strcmp(arg, "--show-cdup")) {
 				const char *pfx = prefix;
 				if (!is_inside_work_tree()) {
diff --git a/cache.h b/cache.h
index 38985aa..4687096 100644
--- a/cache.h
+++ b/cache.h
@@ -319,6 +319,19 @@ extern const char *get_git_work_tree(void);
 extern const char *read_gitfile_gently(const char *path);
 extern void set_git_work_tree(const char *tree);
 
+extern int sparse_checkout_enabled();
+extern char **get_sparse_prefix(void);
+extern const char *get_sparse_prefix_str(void);
+extern char **save_sparse_prefix();
+extern char **restore_sparse_prefix(char **prefix);
+extern int outside_sparse_prefix(const char *prefix);
+extern int index_outside_sparse_prefix(const char *prefix);
+extern void set_sparse_prefix(const char *prefix);
+extern char **split_prefix(const char *env);
+extern char **combine_prefix_list(char **p1, char **p2);
+extern void free_prefix_list(char **prefix_list);
+extern int outside_prefix_list(char **iprefix, const char *prefix);
+
 #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES"
 
 extern const char **get_pathspec(const char *prefix, const char **pathspec);
diff --git a/config.c b/config.c
index 1e066c7..e7b457b 100644
--- a/config.c
+++ b/config.c
@@ -467,6 +467,13 @@ static int git_default_core_config(const char *var, const char *value)
 		return 0;
 	}
 
+	if (!strcmp(var, "core.sparsecheckout")) {
+		if (!value)
+			return config_error_nonbool(var);
+		set_sparse_prefix(value);
+		return 0;
+	}
+
 	/* Add other config variables here and to Documentation/config.txt. */
 	return 0;
 }
diff --git a/environment.c b/environment.c
index 4a88a17..94e39b8 100644
--- a/environment.c
+++ b/environment.c
@@ -46,9 +46,132 @@ enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
 char *git_work_tree_cfg;
 static char *work_tree;
 
+static char **sparse_prefix;
+
 static const char *git_dir;
 static char *git_object_dir, *git_index_file, *git_refs_dir, *git_graft_file;
 
+static char *append_slash(const char *prefix, int len)
+{
+	char *new_prefix;
+
+	if (!*prefix)
+		return NULL;
+
+	if (prefix[len-1] == '/')
+		return xstrndup(prefix, len);
+
+	new_prefix = xmalloc(len+2);
+	memcpy(new_prefix, prefix, len);
+	new_prefix[len] = '/';
+	new_prefix[len+1] = '\0';
+	return new_prefix;
+}
+
+/* this should be sorted as same order as index */
+static int prefix_compare(const void *prefix1_, const void *prefix2_)
+{
+	const char *prefix1 = *(const char**)prefix1_;
+	const char *prefix2 = *(const char**)prefix2_;
+	int len1 = strlen(prefix1);
+	int len2 = strlen(prefix2);
+	int len = len1 < len2 ? len1 : len2;
+	int cmp = memcmp(prefix1, prefix2, len);
+	if (cmp)
+		return cmp;
+	if (len1 < len2)
+		return -1;
+	if (len1 > len2)
+		return 1;
+	return 0;
+}
+
+void free_prefix_list(char **prefix_list)
+{
+	char **prefix = prefix_list;
+
+	if (!prefix)
+		return;
+
+	while (*prefix) {
+		free(*prefix);
+		prefix++;
+	}
+	free(prefix_list);
+}
+
+char **split_prefix(const char *env)
+{
+	int prefix_nr = 0;
+	int prefix_alloc = 0;
+	char **prefix_list = NULL;
+
+	if (!env)
+		return NULL;
+
+	do {
+		const char *sep = strchr(env, ':');
+		int len = sep ? sep - env : strlen(env);
+		if (prefix_alloc <= prefix_nr+1) {
+			prefix_alloc = alloc_nr(prefix_alloc);
+			prefix_list = xrealloc(prefix_list,
+						prefix_alloc * sizeof(*prefix_list));
+		}
+		prefix_list[prefix_nr++] = append_slash(env, len);
+		env += sep ? len+1 : len;
+	} while (*env);
+	prefix_list[prefix_nr] = NULL;
+	qsort(prefix_list, prefix_nr, sizeof(*prefix_list), prefix_compare);
+	return prefix_list;
+}
+
+char **combine_prefix_list(char **p1, char **p2)
+{
+	int len1 = 0, len2 = 0;
+	char **p, **p12, *last_prefix;
+	char **result, **result_p;
+
+	/*
+	 * if either of them is null, full access,
+	 * combining them would give full access as well
+	 */
+	if (!p1 || !p2)
+		return NULL;
+
+	for (p = p1; *p; p++)
+		len1++;
+	for (p = p2; *p; p++)
+		len2++;
+
+	p12 = xmalloc((len1+len2+1)*sizeof(*p12));
+	result = xmalloc((len1+len2+1)*sizeof(*result));
+	memcpy(p12, p1, len1*sizeof(*p12));
+	memcpy(p12+len1, p2, (len2+1)*sizeof(*p12));
+	qsort(p12, len1+len2, sizeof(*p12), prefix_compare);
+
+	p = p12;
+	last_prefix = *p;
+	p++;
+	result_p = result;
+	*result_p = xstrdup(last_prefix);
+	result_p++;
+	while (*p) {
+		if (!strcmp(*p, last_prefix)) {
+			p++;
+			continue;
+		}
+		if (!prefixcmp(*p, last_prefix)) {
+			p++;
+			continue;
+		}
+		*result_p = xstrdup(*p);
+		result_p++;
+		p++;
+	}
+	*result_p = NULL;
+	return result;
+}
+
 static void setup_git_env(void)
 {
 	git_dir = getenv(GIT_DIR_ENVIRONMENT);
@@ -122,6 +245,104 @@ const char *get_git_work_tree(void)
 	return work_tree;
 }
 
+void set_sparse_prefix(const char *flat_sparse_prefix)
+{
+	free_prefix_list(sparse_prefix);
+	sparse_prefix = split_prefix(flat_sparse_prefix);
+}
+
+char **get_sparse_prefix()
+{
+	return sparse_prefix;
+}
+
+const char *get_sparse_prefix_str()
+{
+	static char **sparse_prefix = NULL;
+	static char *sparse_prefix_str = NULL;
+	int len;
+	char **prefix;
+
+	if (sparse_prefix == get_sparse_prefix())
+		return sparse_prefix ? sparse_prefix_str : "";
+
+	sparse_prefix = get_sparse_prefix();
+
+	if (!sparse_prefix)
+		return "";
+
+	len = 0;
+	for (prefix = sparse_prefix; *prefix; prefix++)
+		len += strlen(*prefix)+1;
+	if (sparse_prefix_str)
+		free(sparse_prefix_str);
+	sparse_prefix_str = xmalloc(len);
+
+	prefix = sparse_prefix;
+	len = strlen(*prefix);
+	if ((*prefix)[len-1] == '/')
+		len--;
+	memcpy(sparse_prefix_str, *prefix, len);
+	prefix++;
+	while (*prefix) {
+		int len2 = strlen(*prefix);
+		sparse_prefix_str[len++] = ':';
+		if ((*prefix)[len2-1] == '/')
+			len2--;
+		memcpy(sparse_prefix_str+len, *prefix, len2);
+		len += len2;
+		prefix++;
+	}
+	sparse_prefix_str[len] = 0;
+	return sparse_prefix_str;
+}
+
+char **save_sparse_prefix()
+{
+	char **prefix = sparse_prefix;
+	sparse_prefix = NULL;
+	return prefix;
+}
+
+char **restore_sparse_prefix(char **prefix)
+{
+	char **old_prefix = sparse_prefix;
+	sparse_prefix = prefix;
+	return old_prefix;
+}
+
+int outside_prefix_list(char **iprefix, const char *prefix)
+{
+	if (!iprefix)
+		return 0;
+
+	while (*iprefix) {
+		if (!prefixcmp(prefix, *iprefix))
+			return 0;
+		iprefix++;
+	}
+	return 1;
+}
+
+int sparse_checkout_enabled()
+{
+	static int disable_sparse_checkout = -1;
+	if (disable_sparse_checkout == -1)
+		disable_sparse_checkout = getenv("GIT_SPARSE_CHECKOUT_INDEX_ONLY") != NULL;
+	return !disable_sparse_checkout && get_sparse_prefix();
+}
+
+
+int outside_sparse_prefix(const char *prefix)
+{
+	return sparse_checkout_enabled() && outside_prefix_list(sparse_prefix, prefix);
+}
+
+int index_outside_sparse_prefix(const char *prefix)
+{
+	return outside_prefix_list(sparse_prefix, prefix);
+}
+
 char *get_object_directory(void)
 {
 	if (!git_object_dir)
-- 
1.5.5.GIT

         reply	other threads:[~2008-07-23 14:57 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-07-23 14:57 [PATCH 10/12] git-checkout: support --full and --path to manipulate sparse checkout Nguyễn Thái Ngọc Duy
2008-07-23 14:57 ` [PATCH 08/12] git-clone: support --path to do sparse clone Nguyễn Thái Ngọc Duy
2008-07-23 14:56   ` Nguyễn Thái Ngọc Duy [this message]
2008-07-23 14:55     ` [PATCH 02/12] git-grep: support --no-external-grep Nguyễn Thái Ngọc Duy
2008-07-23 19:01       ` Petr Baudis
2008-07-23 19:05         ` Petr Baudis
2008-07-24 20:26       ` Alex Riesen
2008-07-24 23:16         ` Nguyen Thai Ngoc Duy
2008-07-24 17:19   ` [PATCH 08/12] git-clone: support --path to do sparse clone Jeff King
2008-07-24 17:41     ` sparse fetch, was " Johannes Schindelin
2008-07-24 18:28       ` Jeff King
2008-07-25  0:09         ` Johannes Schindelin
2008-07-25  0:46         ` James Pickens
2008-07-25  0:49           ` sparse fetch, was Re: [PATCH 08/12] git-clone: support --path?to " Jeff King
2008-07-25  8:47         ` sparse fetch, was Re: [PATCH 08/12] git-clone: support --path to " Junio C Hamano
2008-07-25  8:54           ` Sverre Rabbelier
2008-07-24 18:44       ` Nguyen Thai Ngoc Duy
2008-07-24 18:53       ` Petr Baudis
2008-07-24 19:01         ` Sverre Rabbelier
2008-07-25  0:12           ` Johannes Schindelin
2008-07-25  0:42             ` Petr Baudis
2008-07-25  8:14             ` Sverre Rabbelier
2008-07-24 18:47     ` Nguyen Thai Ngoc Duy

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=20080723145603.GA29079@laptop \
    --to=pclouds@gmail.com \
    --cc=git@vger.kernel.org \
    /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).