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
next prev 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.