* [RFC 00/11] Make reference pruning more configurable
@ 2013-12-04 5:44 Michael Haggerty
2013-12-04 5:44 ` [RFC 01/11] get_stale_heads(): allow limiting to refname patterns Michael Haggerty
` (11 more replies)
0 siblings, 12 replies; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 5:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Michael Haggerty
This patch series applies on top of
mh/fetch-tags-in-addition-to-normal-refs
and has some minor conflicts with that branch (mostly related to
documentation).
Let me state in advance that I personally think that the features
implemented in this patch series are overkill. But since it was
already implemented, I thought I would throw it out there and see if
anybody likes it.
This patch series makes it possible for the user to specify explicitly
which reference namespaces should be subjected to pruning when
fetching from a remote.
* It allows a <pattern> to be passed to the --prune option for the
following commands:
git fetch --prune=<pattern> [...]
git remote update --prune=<pattern> [...]
git remote prune --prune=<pattern> [...]
Only references that match the specified pattern(s) are
considered for pruning.
git remote show --prune=<pattern> [...]
Only show prunable references that match the specified
pattern(s).
The --prune=<pattern> option can be specified multiple times.
* It introduces the following multivalued configuration values:
fetch.pruneRef
remote.<name>.pruneRef
Configuration settings for setting the default
"--prune=<pattern>" options, globally and per-remote.
Background: I started working on this feature as my first approach to
solving the problem that
git fetch --tags --prune
can nuke tags unrelated to the remote being fetched from. Only later
did I hit upon the better solution that is implemented in
mh/fetch-tags-in-addition-to-normal-refs, namely to change the
semantics of the --tags option to *not* subject tags to pruning.
But even though "--prune=<pattern>" is no longer needed to prevent tag
nuking, it might be useful to somebody for other purposes, and
therefore I am submitting it to the list as an RFC. Maybe there is a
use case associated with non-branch, non-tag references, like perhaps
Gerrit pull request-related references?
Personally, I am -0 on this series. I think it adds more complication
(code, documentation, etc) than its usefulness justifies. I think the
functionality in mh/fetch-tags-in-addition-to-normal-refs (which we
want in any case!) will satisfy 99% of users and I can't think of use
cases where additional configurability of reference pruning is needed.
So, if anybody can think of a compelling use case for this feature,
please make your case!
Michael
Michael Haggerty (11):
get_stale_heads(): allow limiting to refname patterns
remote.c: add infrastructure for parsing --prune options
fetch: use the new functions for handling --prune options
remote: use the new functions for handling --prune options
remote.c: add infrastructure to handle --prune=<pattern>
fetch --prune: allow refname patterns to be specified
remote update --prune: allow refname patterns to be specified
string_list_append_list(): new function
remote prune: allow --prune=<pattern> options
remote show: allow --prune=<pattern> options
remote: allow prune patterns to be configured
Documentation/config.txt | 28 ++++--
Documentation/fetch-options.txt | 13 ++-
Documentation/git-remote.txt | 29 +++++--
Documentation/technical/api-string-list.txt | 10 ++-
builtin/fetch.c | 43 +++------
builtin/remote.c | 85 ++++++++++++------
remote.c | 130 +++++++++++++++++++++++++++-
remote.h | 48 +++++++++-
string-list.c | 9 ++
string-list.h | 8 ++
t/t5505-remote.sh | 88 +++++++++++++++++++
t/t5510-fetch.sh | 25 ++++++
12 files changed, 441 insertions(+), 75 deletions(-)
--
1.8.4.3
^ permalink raw reply [flat|nested] 15+ messages in thread
* [RFC 01/11] get_stale_heads(): allow limiting to refname patterns
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
@ 2013-12-04 5:44 ` Michael Haggerty
2013-12-04 5:44 ` [RFC 02/11] remote.c: add infrastructure for parsing --prune options Michael Haggerty
` (10 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 5:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Michael Haggerty
Add a "patterns" argument to get_stale_heads(). If it is non-NULL,
then only refnames matching one of the glob patterns in the string
list will be included in the output.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
builtin/fetch.c | 3 ++-
builtin/remote.c | 3 ++-
remote.c | 26 ++++++++++++++++++++++++--
remote.h | 9 +++++++--
4 files changed, 35 insertions(+), 6 deletions(-)
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 3d978eb..9a04512 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -711,7 +711,8 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map)
static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map)
{
int result = 0;
- struct ref *ref, *stale_refs = get_stale_heads(refs, ref_count, ref_map);
+ struct ref *stale_refs = get_stale_heads(refs, ref_count, ref_map, NULL);
+ struct ref *ref;
const char *dangling_msg = dry_run
? _(" (%s will become dangling)")
: _(" (%s has become dangling)");
diff --git a/builtin/remote.c b/builtin/remote.c
index f532f35..c08dfa8 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -347,7 +347,8 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
string_list_append(&states->tracked, abbrev_branch(ref->name));
}
stale_refs = get_stale_heads(states->remote->fetch,
- states->remote->fetch_refspec_nr, fetch_map);
+ states->remote->fetch_refspec_nr,
+ fetch_map, NULL);
for (ref = stale_refs; ref; ref = ref->next) {
struct string_list_item *item =
string_list_append(&states->stale, abbrev_branch(ref->name));
diff --git a/remote.c b/remote.c
index dc56619..075ed71 100644
--- a/remote.c
+++ b/remote.c
@@ -1986,13 +1986,31 @@ struct stale_heads_info {
struct ref **stale_refs_tail;
struct refspec *refs;
int ref_count;
+ struct string_list *patterns;
};
static int get_stale_heads_cb(const char *refname,
- const unsigned char *sha1, int flags, void *cb_data)
+ const unsigned char *sha1, int flags,
+ void *cb_data)
{
struct stale_heads_info *info = cb_data;
struct refspec query;
+ struct string_list *patterns = info->patterns;
+
+ if (patterns) {
+ int refname_matches = 0;
+ struct string_list_item *item;
+
+ for_each_string_list_item(item, patterns) {
+ if (!fnmatch(item->string, refname, 0)) {
+ refname_matches = 1;
+ break;
+ }
+ }
+ if (!refname_matches)
+ return 0;
+ }
+
memset(&query, 0, sizeof(struct refspec));
query.dst = (char *)refname;
@@ -2014,15 +2032,19 @@ static int get_stale_heads_cb(const char *refname,
return 0;
}
-struct ref *get_stale_heads(struct refspec *refs, int ref_count, struct ref *fetch_map)
+struct ref *get_stale_heads(struct refspec *refs, int ref_count,
+ struct ref *fetch_map,
+ struct string_list *patterns)
{
struct ref *ref, *stale_refs = NULL;
struct string_list ref_names = STRING_LIST_INIT_NODUP;
struct stale_heads_info info;
+
info.ref_names = &ref_names;
info.stale_refs_tail = &stale_refs;
info.refs = refs;
info.ref_count = ref_count;
+ info.patterns = patterns;
for (ref = fetch_map; ref; ref = ref->next)
string_list_append(&ref_names, ref->name);
sort_string_list(&ref_names);
diff --git a/remote.h b/remote.h
index c07eb99..afa3792 100644
--- a/remote.h
+++ b/remote.h
@@ -234,8 +234,13 @@ struct ref *guess_remote_head(const struct ref *head,
const struct ref *refs,
int all);
-/* Return refs which no longer exist on remote */
-struct ref *get_stale_heads(struct refspec *refs, int ref_count, struct ref *fetch_map);
+/*
+ * Return refs that no longer exist on remote and that match one of
+ * the patterns.
+ */
+struct ref *get_stale_heads(struct refspec *refs, int ref_count,
+ struct ref *fetch_map,
+ struct string_list *patterns);
/*
* Compare-and-swap
--
1.8.4.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC 02/11] remote.c: add infrastructure for parsing --prune options
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
2013-12-04 5:44 ` [RFC 01/11] get_stale_heads(): allow limiting to refname patterns Michael Haggerty
@ 2013-12-04 5:44 ` Michael Haggerty
2013-12-04 12:57 ` Duy Nguyen
2013-12-04 5:44 ` [RFC 03/11] fetch: use the new functions for handling " Michael Haggerty
` (9 subsequent siblings)
11 siblings, 1 reply; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 5:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Michael Haggerty
For now, only handle --prune/--no-prune. But handle the option via a
callback so that in the future --prune=PATTERN can be implemented.
The new functions are not yet used.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
remote.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
remote.h | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 97 insertions(+)
diff --git a/remote.c b/remote.c
index 075ed71..297e52f 100644
--- a/remote.c
+++ b/remote.c
@@ -7,6 +7,7 @@
#include "dir.h"
#include "tag.h"
#include "string-list.h"
+#include "argv-array.h"
#include "mergesort.h"
enum map_direction { FROM_SRC, FROM_DST };
@@ -58,6 +59,67 @@ static struct rewrites rewrites_push;
#define BUF_SIZE (2048)
static char buffer[BUF_SIZE];
+int prune_option_parse(const struct option *opt, const char *arg, int unset)
+{
+ struct prune_option *target = opt->value;
+
+ if (unset) {
+ target->prune = 0;
+ } else {
+ target->prune = 1;
+ }
+ return 0;
+}
+
+static int git_fetch_config(const char *k, const char *v, void *cb)
+{
+ int *fetch_prune_config = cb;
+
+ if (!strcmp(k, "fetch.prune")) {
+ *fetch_prune_config = git_config_bool(k, v);
+ return 0;
+ }
+ return 0;
+}
+
+void prune_option_fill(struct remote *remote,
+ struct prune_option *prune_option, int default_prune)
+{
+ if (prune_option->prune < 0) {
+ /*
+ * The user specified neither --prune nor --no-prune;
+ * use the configured value of remote.<name>.prune or
+ * fetch.prune:
+ */
+ if (remote->prune >= 0) {
+ prune_option->prune = remote->prune;
+ } else {
+ int fetch_prune_config = -1;
+
+ git_config(git_fetch_config, &fetch_prune_config);
+
+ if (fetch_prune_config >= 0)
+ prune_option->prune = fetch_prune_config;
+ else
+ prune_option->prune = default_prune;
+ }
+ }
+}
+
+void argv_push_prune_option(struct argv_array *argv,
+ struct prune_option *prune_option)
+{
+ if (prune_option->prune != -1)
+ argv_array_pushf(argv,
+ prune_option->prune
+ ? "--prune"
+ : "--no-prune");
+}
+
+void prune_option_clear(struct prune_option *prune_option)
+{
+}
+
static int valid_remote(const struct remote *remote)
{
return (!!remote->url) || (!!remote->foreign_vcs);
diff --git a/remote.h b/remote.h
index afa3792..21ff4cb 100644
--- a/remote.h
+++ b/remote.h
@@ -53,6 +53,40 @@ struct remote {
char *http_proxy;
};
+/* Structure to hold parsed --prune/--no-prune options */
+struct prune_option {
+ /* Should we prune at all? -1 is indeterminate. */
+ int prune;
+};
+
+#define PRUNE_OPTION_INIT { -1 }
+
+/* parse_opts() callback for --prune/--no-prune options */
+int prune_option_parse(const struct option *opt, const char *arg, int unset);
+
+/*
+ * Fill in prune_option for the specified remote, given the
+ * prune_option values parsed from the command-line. default_prune
+ * specifies whether pruning should default to true or false if it has
+ * not been configured explicitly.
+ */
+void prune_option_fill(struct remote *remote,
+ struct prune_option *prune_option, int default_prune);
+
+/*
+ * Add --prune/--prune=<pattern>/--no-prune options to the argv_array
+ * to represent the options in prune_options.
+ */
+struct argv_array;
+void argv_push_prune_option(struct argv_array *argv,
+ struct prune_option *prune_option);
+
+/*
+ * Free any resources used by *prune_option (but not *prune_option
+ * itself).
+ */
+void prune_option_clear(struct prune_option *prune_option);
+
struct remote *remote_get(const char *name);
struct remote *pushremote_get(const char *name);
int remote_is_configured(const char *name);
@@ -238,6 +272,7 @@ struct ref *guess_remote_head(const struct ref *head,
* Return refs that no longer exist on remote and that match one of
* the patterns.
*/
+struct string_list;
struct ref *get_stale_heads(struct refspec *refs, int ref_count,
struct ref *fetch_map,
struct string_list *patterns);
--
1.8.4.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC 03/11] fetch: use the new functions for handling --prune options
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
2013-12-04 5:44 ` [RFC 01/11] get_stale_heads(): allow limiting to refname patterns Michael Haggerty
2013-12-04 5:44 ` [RFC 02/11] remote.c: add infrastructure for parsing --prune options Michael Haggerty
@ 2013-12-04 5:44 ` Michael Haggerty
2013-12-04 5:44 ` [RFC 04/11] remote: " Michael Haggerty
` (8 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 5:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Michael Haggerty
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
builtin/fetch.c | 36 ++++++++----------------------------
1 file changed, 8 insertions(+), 28 deletions(-)
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 9a04512..fcc06a4 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -30,8 +30,7 @@ enum {
TAGS_SET = 2
};
-static int fetch_prune_config = -1; /* unspecified */
-static int prune = -1; /* unspecified */
+static struct prune_option prune_option = PRUNE_OPTION_INIT;
#define PRUNE_BY_DEFAULT 0 /* do we prune by default? */
static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosity;
@@ -59,15 +58,6 @@ static int option_parse_recurse_submodules(const struct option *opt,
return 0;
}
-static int git_fetch_config(const char *k, const char *v, void *cb)
-{
- if (!strcmp(k, "fetch.prune")) {
- fetch_prune_config = git_config_bool(k, v);
- return 0;
- }
- return 0;
-}
-
static struct option builtin_fetch_options[] = {
OPT__VERBOSITY(&verbosity),
OPT_BOOL(0, "all", &all,
@@ -83,8 +73,9 @@ static struct option builtin_fetch_options[] = {
N_("fetch all tags and associated objects"), TAGS_SET),
OPT_SET_INT('n', NULL, &tags,
N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
- OPT_BOOL('p', "prune", &prune,
- N_("prune remote-tracking branches no longer on remote")),
+ { OPTION_CALLBACK, 'p', "prune", &prune_option, N_("pattern"),
+ N_("prune remote-tracking branches no longer on remote"),
+ PARSE_OPT_NOARG, prune_option_parse },
{ OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"),
N_("control recursive fetching of submodules"),
PARSE_OPT_OPTARG, option_parse_recurse_submodules },
@@ -848,7 +839,7 @@ static int do_fetch(struct transport *transport,
retcode = 1;
goto cleanup;
}
- if (prune) {
+ if (prune_option.prune) {
/*
* We only prune based on refspecs specified
* explicitly (via command line or configuration); we
@@ -935,8 +926,7 @@ static void add_options_to_argv(struct argv_array *argv)
{
if (dry_run)
argv_array_push(argv, "--dry-run");
- if (prune != -1)
- argv_array_push(argv, prune ? "--prune" : "--no-prune");
+ argv_push_prune_option(argv, &prune_option);
if (update_head_ok)
argv_array_push(argv, "--update-head-ok");
if (force)
@@ -1002,17 +992,9 @@ static int fetch_one(struct remote *remote, int argc, const char **argv)
die(_("No remote repository specified. Please, specify either a URL or a\n"
"remote name from which new revisions should be fetched."));
- gtransport = prepare_transport(remote);
+ prune_option_fill(remote, &prune_option, PRUNE_BY_DEFAULT);
- if (prune < 0) {
- /* no command line request */
- if (0 <= gtransport->remote->prune)
- prune = gtransport->remote->prune;
- else if (0 <= fetch_prune_config)
- prune = fetch_prune_config;
- else
- prune = PRUNE_BY_DEFAULT;
- }
+ gtransport = prepare_transport(remote);
if (argc > 0) {
int j = 0;
@@ -1063,8 +1045,6 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
for (i = 1; i < argc; i++)
strbuf_addf(&default_rla, " %s", argv[i]);
- git_config(git_fetch_config, NULL);
-
argc = parse_options(argc, argv, prefix,
builtin_fetch_options, builtin_fetch_usage, 0);
--
1.8.4.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC 04/11] remote: use the new functions for handling --prune options
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
` (2 preceding siblings ...)
2013-12-04 5:44 ` [RFC 03/11] fetch: use the new functions for handling " Michael Haggerty
@ 2013-12-04 5:44 ` Michael Haggerty
2013-12-04 5:44 ` [RFC 05/11] remote.c: add infrastructure to handle --prune=<pattern> Michael Haggerty
` (7 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 5:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Michael Haggerty
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
builtin/remote.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/builtin/remote.c b/builtin/remote.c
index c08dfa8..09b965a 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -1372,10 +1372,12 @@ static int get_remote_default(const char *key, const char *value, void *priv)
static int update(int argc, const char **argv)
{
- int i, prune = -1;
+ int i;
+ struct prune_option prune_option = PRUNE_OPTION_INIT;
struct option options[] = {
- OPT_BOOL('p', "prune", &prune,
- N_("prune remotes after fetching")),
+ { OPTION_CALLBACK, 'p', "prune", &prune_option, N_("pattern"),
+ N_("prune remotes after fetching"),
+ PARSE_OPT_NOARG, prune_option_parse },
OPT_END()
};
struct argv_array fetch_argv = ARGV_ARRAY_INIT;
@@ -1387,8 +1389,7 @@ static int update(int argc, const char **argv)
argv_array_push(&fetch_argv, "fetch");
- if (prune != -1)
- argv_array_push(&fetch_argv, prune ? "--prune" : "--no-prune");
+ argv_push_prune_option(&fetch_argv, &prune_option);
if (verbose)
argv_array_push(&fetch_argv, "-v");
argv_array_push(&fetch_argv, "--multiple");
--
1.8.4.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC 05/11] remote.c: add infrastructure to handle --prune=<pattern>
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
` (3 preceding siblings ...)
2013-12-04 5:44 ` [RFC 04/11] remote: " Michael Haggerty
@ 2013-12-04 5:44 ` Michael Haggerty
2013-12-04 5:44 ` [RFC 06/11] fetch --prune: allow refname patterns to be specified Michael Haggerty
` (6 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 5:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Michael Haggerty
This will soon be used to allow the user to tell what reference
namespaces should be subjected to pruning. But since the callers of
these functions still use PARSE_OPT_NOARG, the new functionality is
not yet visible.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
remote.c | 35 +++++++++++++++++++++++++++++------
remote.h | 11 +++++++----
2 files changed, 36 insertions(+), 10 deletions(-)
diff --git a/remote.c b/remote.c
index 297e52f..89c9eaa 100644
--- a/remote.c
+++ b/remote.c
@@ -6,7 +6,6 @@
#include "revision.h"
#include "dir.h"
#include "tag.h"
-#include "string-list.h"
#include "argv-array.h"
#include "mergesort.h"
@@ -64,9 +63,16 @@ int prune_option_parse(const struct option *opt, const char *arg, int unset)
struct prune_option *target = opt->value;
if (unset) {
+ if (arg) {
+ error("--no-prune must not be used with an argument");
+ return 1;
+ }
target->prune = 0;
+ string_list_clear(&target->prune_patterns, 0);
} else {
target->prune = 1;
+ if (arg)
+ string_list_append(&target->prune_patterns, arg);
}
return 0;
}
@@ -104,20 +110,37 @@ void prune_option_fill(struct remote *remote,
prune_option->prune = default_prune;
}
}
+
+ if (prune_option->prune && !prune_option->prune_patterns.nr) {
+ /*
+ * We want to prune, but no pruning patterns were
+ * specified on the command line. Default to "*".
+ */
+ string_list_append(&prune_option->prune_patterns, "*");
+ }
}
void argv_push_prune_option(struct argv_array *argv,
struct prune_option *prune_option)
{
- if (prune_option->prune != -1)
- argv_array_pushf(argv,
- prune_option->prune
- ? "--prune"
- : "--no-prune");
+ if (prune_option->prune != -1) {
+ if (prune_option->prune && prune_option->prune_patterns.nr) {
+ struct string_list_item *item;
+
+ for_each_string_list_item(item, &prune_option->prune_patterns)
+ argv_array_pushf(argv, "--prune=%s", item->string);
+ } else {
+ argv_array_pushf(argv,
+ prune_option->prune
+ ? "--prune"
+ : "--no-prune");
+ }
+ }
}
void prune_option_clear(struct prune_option *prune_option)
{
+ string_list_clear(&prune_option->prune_patterns, 0);
}
static int valid_remote(const struct remote *remote)
diff --git a/remote.h b/remote.h
index 21ff4cb..a484290 100644
--- a/remote.h
+++ b/remote.h
@@ -2,6 +2,7 @@
#define REMOTE_H
#include "parse-options.h"
+#include "string-list.h"
enum {
REMOTE_CONFIG,
@@ -53,15 +54,18 @@ struct remote {
char *http_proxy;
};
-/* Structure to hold parsed --prune/--no-prune options */
+/* Structure to hold parsed --prune/--prune=<pattern>/--no-prune options */
struct prune_option {
/* Should we prune at all? -1 is indeterminate. */
int prune;
+
+ /* Arguments passed to --prune=<pattern> */
+ struct string_list prune_patterns;
};
-#define PRUNE_OPTION_INIT { -1 }
+#define PRUNE_OPTION_INIT { -1, STRING_LIST_INIT_DUP }
-/* parse_opts() callback for --prune/--no-prune options */
+/* parse_opts() callback for --prune/--prune=<pattern>/--no-prune options */
int prune_option_parse(const struct option *opt, const char *arg, int unset);
/*
@@ -272,7 +276,6 @@ struct ref *guess_remote_head(const struct ref *head,
* Return refs that no longer exist on remote and that match one of
* the patterns.
*/
-struct string_list;
struct ref *get_stale_heads(struct refspec *refs, int ref_count,
struct ref *fetch_map,
struct string_list *patterns);
--
1.8.4.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC 06/11] fetch --prune: allow refname patterns to be specified
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
` (4 preceding siblings ...)
2013-12-04 5:44 ` [RFC 05/11] remote.c: add infrastructure to handle --prune=<pattern> Michael Haggerty
@ 2013-12-04 5:44 ` Michael Haggerty
2013-12-04 5:44 ` [RFC 07/11] remote update " Michael Haggerty
` (5 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 5:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Michael Haggerty
Allow optional arguments to be passed to "git fetch --prune" to choose
which references are subject to pruning. The default, if no argument
is specified, is to prune all references as before.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
Documentation/fetch-options.txt | 6 +++++-
builtin/fetch.c | 8 ++++++--
t/t5510-fetch.sh | 12 ++++++++++++
3 files changed, 23 insertions(+), 3 deletions(-)
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index f0ef7d0..61d3f75 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -40,7 +40,7 @@ ifndef::git-pull[]
specified. No <refspec>s may be specified.
-p::
---prune::
+--prune[=<pattern>]::
After fetching, remove any remote-tracking references that no
longer exist on the remote. Tags are not subject to pruning
if they are fetched only because of the default tag
@@ -49,6 +49,10 @@ ifndef::git-pull[]
line or in the remote configuration, for example if the remote
was cloned with the --mirror option), then they are also
subject to pruning.
++
+If pattern is specified, then it should be a glob pattern, and pruning
+is further restricted to references whose names match the pattern.
+This option can be specified multiple times.
endif::git-pull[]
ifndef::git-pull[]
diff --git a/builtin/fetch.c b/builtin/fetch.c
index fcc06a4..2cb48a6 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -73,9 +73,12 @@ static struct option builtin_fetch_options[] = {
N_("fetch all tags and associated objects"), TAGS_SET),
OPT_SET_INT('n', NULL, &tags,
N_("do not fetch all tags (--no-tags)"), TAGS_UNSET),
- { OPTION_CALLBACK, 'p', "prune", &prune_option, N_("pattern"),
+ { OPTION_CALLBACK, 'p', NULL, &prune_option, NULL,
N_("prune remote-tracking branches no longer on remote"),
PARSE_OPT_NOARG, prune_option_parse },
+ { OPTION_CALLBACK, 0, "prune", &prune_option, N_("pattern"),
+ N_("prune remote-tracking branches (matching pattern, if specified)"),
+ PARSE_OPT_OPTARG, prune_option_parse },
{ OPTION_CALLBACK, 0, "recurse-submodules", NULL, N_("on-demand"),
N_("control recursive fetching of submodules"),
PARSE_OPT_OPTARG, option_parse_recurse_submodules },
@@ -702,7 +705,8 @@ static int fetch_refs(struct transport *transport, struct ref *ref_map)
static int prune_refs(struct refspec *refs, int ref_count, struct ref *ref_map)
{
int result = 0;
- struct ref *stale_refs = get_stale_heads(refs, ref_count, ref_map, NULL);
+ struct ref *stale_refs = get_stale_heads(refs, ref_count, ref_map,
+ &prune_option.prune_patterns);
struct ref *ref;
const char *dangling_msg = dry_run
? _(" (%s will become dangling)")
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 5d4581d..42eb21f 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -94,6 +94,18 @@ test_expect_success 'fetch --prune on its own works as expected' '
test_must_fail git rev-parse origin/extrabranch
'
+test_expect_success 'fetch --prune with arguments' '
+ cd "$D" &&
+ git clone . prune-args &&
+ cd prune-args &&
+ git update-ref refs/remotes/origin/branch1 master &&
+ git update-ref refs/remotes/origin/branch2 master &&
+
+ git fetch --prune="refs/remotes/origin/*1" origin &&
+ test_must_fail git rev-parse origin/branch1 &&
+ git rev-parse origin/branch2
+'
+
test_expect_success 'fetch --prune with a branch name keeps branches' '
cd "$D" &&
git clone . prune-branch &&
--
1.8.4.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC 07/11] remote update --prune: allow refname patterns to be specified
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
` (5 preceding siblings ...)
2013-12-04 5:44 ` [RFC 06/11] fetch --prune: allow refname patterns to be specified Michael Haggerty
@ 2013-12-04 5:44 ` Michael Haggerty
2013-12-04 5:44 ` [RFC 08/11] string_list_append_list(): new function Michael Haggerty
` (4 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 5:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Michael Haggerty
Allow optional arguments to be passed to "git remote update --prune"
to choose which references are subject to pruning. The default, if no
argument is specified, is to prune all references as before.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
Documentation/git-remote.txt | 7 +++++--
builtin/remote.c | 9 ++++++---
t/t5505-remote.sh | 13 +++++++++++++
3 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index 2507c8b..02e50a9 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -20,7 +20,8 @@ SYNOPSIS
'git remote set-url --delete' [--push] <name> <url>
'git remote' [-v | --verbose] 'show' [-n] <name>...
'git remote prune' [-n | --dry-run] <name>...
-'git remote' [-v | --verbose] 'update' [-p | --prune] [(<group> | <remote>)...]
+'git remote' [-v | --verbose] 'update' [-p | --no-prune | --prune[=<pattern>]...]
+ [(<group> | <remote>)...]
DESCRIPTION
-----------
@@ -168,7 +169,9 @@ remotes.default is not defined, all remotes which do not have the
configuration parameter remote.<name>.skipDefaultUpdate set to true will
be updated. (See linkgit:git-config[1]).
+
-With `--prune` option, prune all the remotes that are updated.
+The options `--prune`, `--no-prune`, and `--prune=<pattern>` affect
+whether remote-tracking branches associated with the remotes are
+pruned. See linkgit:git-fetch[1] for more information.
DISCUSSION
diff --git a/builtin/remote.c b/builtin/remote.c
index 09b965a..6aab923 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -16,7 +16,7 @@ static const char * const builtin_remote_usage[] = {
N_("git remote set-head <name> (-a | --auto | -d | --delete |<branch>)"),
N_("git remote [-v | --verbose] show [-n] <name>"),
N_("git remote prune [-n | --dry-run] <name>"),
- N_("git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]"),
+ N_("git remote [-v | --verbose] update [-p | --prune[=<pattern>] | --no-prune] [(<group> | <remote>)...]"),
N_("git remote set-branches [--add] <name> <branch>..."),
N_("git remote set-url [--push] <name> <newurl> [<oldurl>]"),
N_("git remote set-url --add <name> <newurl>"),
@@ -1375,9 +1375,12 @@ static int update(int argc, const char **argv)
int i;
struct prune_option prune_option = PRUNE_OPTION_INIT;
struct option options[] = {
- { OPTION_CALLBACK, 'p', "prune", &prune_option, N_("pattern"),
- N_("prune remotes after fetching"),
+ { OPTION_CALLBACK, 'p', NULL, &prune_option, NULL,
+ N_("prune remote-tracking branches no longer on remote"),
PARSE_OPT_NOARG, prune_option_parse },
+ { OPTION_CALLBACK, 0, "prune", &prune_option, N_("pattern"),
+ N_("prune remote-tracking branches (matching pattern, if specified)"),
+ PARSE_OPT_OPTARG, prune_option_parse },
OPT_END()
};
struct argv_array fetch_argv = ARGV_ARRAY_INIT;
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 8f6e392..0dffe47 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -614,6 +614,19 @@ test_expect_success 'update --prune' '
)
'
+test_expect_success 'update --prune with argument' '
+ git clone one update-prune-arg &&
+ (
+ cd update-prune-arg &&
+ git update-ref refs/remotes/origin/branch1 master &&
+ git update-ref refs/remotes/origin/branch2 master &&
+
+ git remote update --prune="refs/remotes/*1" origin &&
+ test_must_fail git rev-parse origin/branch1 &&
+ git rev-parse origin/branch2
+ )
+'
+
cat >one/expect <<-\EOF
apis/master
apis/side
--
1.8.4.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC 08/11] string_list_append_list(): new function
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
` (6 preceding siblings ...)
2013-12-04 5:44 ` [RFC 07/11] remote update " Michael Haggerty
@ 2013-12-04 5:44 ` Michael Haggerty
2013-12-04 5:44 ` [RFC 09/11] remote prune: allow --prune=<pattern> options Michael Haggerty
` (3 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 5:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Michael Haggerty
Add a new function that appends the strings from one string_list onto
another string_list.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
Documentation/technical/api-string-list.txt | 10 ++++++++--
string-list.c | 9 +++++++++
string-list.h | 8 ++++++++
3 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/Documentation/technical/api-string-list.txt b/Documentation/technical/api-string-list.txt
index 20be348..2072cf7 100644
--- a/Documentation/technical/api-string-list.txt
+++ b/Documentation/technical/api-string-list.txt
@@ -22,8 +22,9 @@ member (you need this if you add things later) and you should set the
`nr` and `alloc` members in that case, too.
. Adds new items to the list, using `string_list_append`,
- `string_list_append_nodup`, `string_list_insert`,
- `string_list_split`, and/or `string_list_split_in_place`.
+ `string_list_append_nodup`, `string_list_append_list`,
+ `string_list_insert`, `string_list_split`, and/or
+ `string_list_split_in_place`.
. Can check if a string is in the list using `string_list_has_string` or
`unsorted_string_list_has_string` and get it from the list using
@@ -141,6 +142,11 @@ write `string_list_insert(...)->util = ...;`.
ownership of a malloc()ed string to a `string_list` that has
`strdup_string` set.
+`string_list_append_list`::
+
+ Append the strings from one string_list to the end of another
+ one.
+
`sort_string_list`::
Sort the list's entries by string value in `strcmp()` order.
diff --git a/string-list.c b/string-list.c
index aabb25e..803acd1 100644
--- a/string-list.c
+++ b/string-list.c
@@ -212,6 +212,15 @@ struct string_list_item *string_list_append(struct string_list *list,
list->strdup_strings ? xstrdup(string) : (char *)string);
}
+void string_list_append_list(struct string_list *dst, struct string_list *src)
+{
+ struct string_list_item *item;
+
+ ALLOC_GROW(dst->items, dst->nr + src->nr, dst->alloc);
+ for_each_string_list_item(item, src)
+ string_list_append(dst, item->string);
+}
+
/* Yuck */
static compare_strings_fn compare_for_qsort;
diff --git a/string-list.h b/string-list.h
index de6769c..7b0ae86 100644
--- a/string-list.h
+++ b/string-list.h
@@ -76,6 +76,14 @@ void string_list_remove_duplicates(struct string_list *sorted_list, int free_uti
struct string_list_item *string_list_append(struct string_list *list, const char *string);
/*
+ * Add all strings from src to the end of dst. If dst->strdup_string
+ * is set, then the strings are copied; otherwise the new
+ * string_list_entries refer to the input strings. src is left
+ * unchanged.
+ */
+void string_list_append_list(struct string_list *dst, struct string_list *src);
+
+/*
* Like string_list_append(), except string is never copied. When
* list->strdup_strings is set, this function can be used to hand
* ownership of a malloc()ed string to list without making an extra
--
1.8.4.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC 09/11] remote prune: allow --prune=<pattern> options
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
` (7 preceding siblings ...)
2013-12-04 5:44 ` [RFC 08/11] string_list_append_list(): new function Michael Haggerty
@ 2013-12-04 5:44 ` Michael Haggerty
2013-12-04 5:44 ` [RFC 10/11] remote show: " Michael Haggerty
` (2 subsequent siblings)
11 siblings, 0 replies; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 5:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Michael Haggerty
Allow "--prune=<pattern>" options to be provided to "git remote prune"
to specify which reference namespaces should be pruned. "--prune"
without an argument and "--no-prune" are disallowed here as they make
no sense.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
Documentation/git-remote.txt | 5 +++-
builtin/remote.c | 67 +++++++++++++++++++++++++++++++-------------
t/t5505-remote.sh | 15 ++++++++++
3 files changed, 66 insertions(+), 21 deletions(-)
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index 02e50a9..9cbc986 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -19,7 +19,7 @@ SYNOPSIS
'git remote set-url --add' [--push] <name> <newurl>
'git remote set-url --delete' [--push] <name> <url>
'git remote' [-v | --verbose] 'show' [-n] <name>...
-'git remote prune' [-n | --dry-run] <name>...
+'git remote prune' [-n | --dry-run] [--prune=<pattern>] <name>...
'git remote' [-v | --verbose] 'update' [-p | --no-prune | --prune[=<pattern>]...]
[(<group> | <remote>)...]
@@ -157,6 +157,9 @@ These stale branches have already been removed from the remote repository
referenced by <name>, but are still locally available in
"remotes/<name>".
+
+With `--prune=<pattern>`, only prune references whose names match
+pattern. This option can be used multiple times.
++
With `--dry-run` option, report what branches will be pruned, but do not
actually prune them.
diff --git a/builtin/remote.c b/builtin/remote.c
index 6aab923..e1d43e2 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -15,7 +15,7 @@ static const char * const builtin_remote_usage[] = {
N_("git remote remove <name>"),
N_("git remote set-head <name> (-a | --auto | -d | --delete |<branch>)"),
N_("git remote [-v | --verbose] show [-n] <name>"),
- N_("git remote prune [-n | --dry-run] <name>"),
+ N_("git remote prune [-n | --dry-run] [--prune=<pattern>] <name>"),
N_("git remote [-v | --verbose] update [-p | --prune[=<pattern>] | --no-prune] [(<group> | <remote>)...]"),
N_("git remote set-branches [--add] <name> <branch>..."),
N_("git remote set-url [--push] <name> <newurl> [<oldurl>]"),
@@ -326,10 +326,12 @@ struct ref_states {
int queried;
};
-static int get_ref_states(const struct ref *remote_refs, struct ref_states *states)
+static int get_ref_states(const struct ref *remote_refs,
+ struct ref_states *states,
+ struct prune_option *prune_option)
{
struct ref *fetch_map = NULL, **tail = &fetch_map;
- struct ref *ref, *stale_refs;
+ struct ref *ref;
int i;
for (i = 0; i < states->remote->fetch_refspec_nr; i++)
@@ -346,15 +348,20 @@ static int get_ref_states(const struct ref *remote_refs, struct ref_states *stat
else
string_list_append(&states->tracked, abbrev_branch(ref->name));
}
- stale_refs = get_stale_heads(states->remote->fetch,
- states->remote->fetch_refspec_nr,
- fetch_map, NULL);
- for (ref = stale_refs; ref; ref = ref->next) {
- struct string_list_item *item =
- string_list_append(&states->stale, abbrev_branch(ref->name));
- item->util = xstrdup(ref->name);
+ if (prune_option->prune) {
+ struct ref *stale_refs =
+ get_stale_heads(states->remote->fetch,
+ states->remote->fetch_refspec_nr,
+ fetch_map,
+ &prune_option->prune_patterns);
+
+ for (ref = stale_refs; ref; ref = ref->next) {
+ struct string_list_item *item =
+ string_list_append(&states->stale, abbrev_branch(ref->name));
+ item->util = xstrdup(ref->name);
+ }
+ free_refs(stale_refs);
}
- free_refs(stale_refs);
free_refs(fetch_map);
sort_string_list(&states->new);
@@ -878,8 +885,9 @@ static int append_ref_to_tracked_list(const char *refname,
}
static int get_remote_ref_states(const char *name,
- struct ref_states *states,
- int query)
+ struct ref_states *states, int query,
+ struct prune_option *prune_option,
+ int default_prune)
{
struct transport *transport;
const struct ref *remote_refs;
@@ -897,8 +905,19 @@ static int get_remote_ref_states(const char *name,
transport_disconnect(transport);
states->queried = 1;
- if (query & GET_REF_STATES)
- get_ref_states(remote_refs, states);
+ if (query & GET_REF_STATES) {
+ struct prune_option remote_prune_option =
+ PRUNE_OPTION_INIT;
+
+ remote_prune_option.prune = prune_option->prune;
+ string_list_append_list(&remote_prune_option.prune_patterns,
+ &prune_option->prune_patterns);
+ prune_option_fill(states->remote,
+ &remote_prune_option,
+ default_prune);
+ get_ref_states(remote_refs, states, &remote_prune_option);
+ prune_option_clear(&remote_prune_option);
+ }
if (query & GET_HEAD_NAMES)
get_head_names(remote_refs, states);
if (query & GET_PUSH_REF_STATES)
@@ -1144,6 +1163,7 @@ static int show_all(void)
static int show(int argc, const char **argv)
{
int no_query = 0, result = 0, query_flag = 0;
+ struct prune_option prune_option = PRUNE_OPTION_INIT;
struct option options[] = {
OPT_BOOL('n', NULL, &no_query, N_("do not query remotes")),
OPT_END()
@@ -1152,6 +1172,7 @@ static int show(int argc, const char **argv)
struct string_list info_list = STRING_LIST_INIT_NODUP;
struct show_info info;
+ prune_option.prune = 1;
argc = parse_options(argc, argv, NULL, options, builtin_remote_show_usage,
0);
@@ -1170,7 +1191,7 @@ static int show(int argc, const char **argv)
const char **url;
int url_nr;
- get_remote_ref_states(*argv, &states, query_flag);
+ get_remote_ref_states(*argv, &states, query_flag, &prune_option, 1);
printf_ln(_("* remote %s"), *argv);
printf_ln(_(" Fetch URL: %s"), states.remote->url_nr > 0 ?
@@ -1268,7 +1289,7 @@ static int set_head(int argc, const char **argv)
} else if (opt_a && !opt_d && argc == 1) {
struct ref_states states;
memset(&states, 0, sizeof(states));
- get_remote_ref_states(argv[0], &states, GET_HEAD_NAMES);
+ get_remote_ref_states(argv[0], &states, GET_HEAD_NAMES, NULL, 0);
if (!states.heads.nr)
result |= error(_("Cannot determine remote HEAD"));
else if (states.heads.nr > 1) {
@@ -1303,7 +1324,8 @@ static int set_head(int argc, const char **argv)
return result;
}
-static int prune_remote(const char *remote, int dry_run)
+static int prune_remote(const char *remote, int dry_run,
+ struct prune_option *prune_option)
{
int result = 0, i;
struct ref_states states;
@@ -1312,7 +1334,7 @@ static int prune_remote(const char *remote, int dry_run)
: _(" %s has become dangling!");
memset(&states, 0, sizeof(states));
- get_remote_ref_states(remote, &states, GET_REF_STATES);
+ get_remote_ref_states(remote, &states, GET_REF_STATES, prune_option, 1);
if (states.stale.nr) {
printf_ln(_("Pruning %s"), remote);
@@ -1344,11 +1366,16 @@ static int prune_remote(const char *remote, int dry_run)
static int prune(int argc, const char **argv)
{
int dry_run = 0, result = 0;
+ struct prune_option prune_option = PRUNE_OPTION_INIT;
struct option options[] = {
+ { OPTION_CALLBACK, 0, "prune", &prune_option, N_("pattern"),
+ N_("prune only references whose names match pattern"),
+ PARSE_OPT_NONEG, prune_option_parse },
OPT__DRY_RUN(&dry_run, N_("dry run")),
OPT_END()
};
+ prune_option.prune = 1;
argc = parse_options(argc, argv, NULL, options, builtin_remote_prune_usage,
0);
@@ -1356,7 +1383,7 @@ static int prune(int argc, const char **argv)
usage_with_options(builtin_remote_prune_usage, options);
for (; argc; argc--, argv++)
- result |= prune_remote(*argv, dry_run);
+ result |= prune_remote(*argv, dry_run, &prune_option);
return result;
}
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 0dffe47..e156174 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -243,6 +243,21 @@ test_expect_success 'prune' '
)
'
+test_expect_success 'prune with --prune' '
+ git clone one prune-prune &&
+ (
+ cd prune-prune &&
+ git update-ref refs/remotes/origin/branch1 master &&
+ git update-ref refs/remotes/origin/branch2 master &&
+
+ test_must_fail git remote prune --prune origin &&
+ test_must_fail git remote prune --no-prune origin &&
+ git remote prune --prune="refs/remotes/*1" origin &&
+ test_must_fail git rev-parse origin/branch1 &&
+ git rev-parse origin/branch2
+ )
+'
+
test_expect_success 'set-head --delete' '
(
cd test &&
--
1.8.4.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC 10/11] remote show: allow --prune=<pattern> options
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
` (8 preceding siblings ...)
2013-12-04 5:44 ` [RFC 09/11] remote prune: allow --prune=<pattern> options Michael Haggerty
@ 2013-12-04 5:44 ` Michael Haggerty
2013-12-04 5:44 ` [RFC 11/11] remote: allow prune patterns to be configured Michael Haggerty
2013-12-04 20:25 ` [RFC 00/11] Make reference pruning more configurable Junio C Hamano
11 siblings, 0 replies; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 5:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Michael Haggerty
By default, show the remote-tracking references that could be pruned.
But if the user specifies --prune=<pattern>, then limit the output to
those matching pattern. And if the user specified --no-prune, then do
not look for stale remote-tracking references at all.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
Documentation/git-remote.txt | 6 ++++++
builtin/remote.c | 3 +++
2 files changed, 9 insertions(+)
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index 9cbc986..dd48474 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -147,6 +147,12 @@ error.
Gives some information about the remote <name>.
+
+With `--prune`, display stale remote-tracking branches that no longer
+exist on the remote (this is the default). With `--prune=<pattern>`,
+only report stale references whose names match <pattern> (this option
+can be used multiple times). With `--no-prune`, do not report stale
+remote-tracking references at all.
++
With `-n` option, the remote heads are not queried first with
`git ls-remote <name>`; cached information is used instead.
diff --git a/builtin/remote.c b/builtin/remote.c
index e1d43e2..293d82d 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -1165,6 +1165,9 @@ static int show(int argc, const char **argv)
int no_query = 0, result = 0, query_flag = 0;
struct prune_option prune_option = PRUNE_OPTION_INIT;
struct option options[] = {
+ { OPTION_CALLBACK, 0, "prune", &prune_option, N_("pattern"),
+ N_("show prunable remote-tracking branches (matching pattern, if specified)"),
+ PARSE_OPT_OPTARG, prune_option_parse },
OPT_BOOL('n', NULL, &no_query, N_("do not query remotes")),
OPT_END()
};
--
1.8.4.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [RFC 11/11] remote: allow prune patterns to be configured
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
` (9 preceding siblings ...)
2013-12-04 5:44 ` [RFC 10/11] remote show: " Michael Haggerty
@ 2013-12-04 5:44 ` Michael Haggerty
2013-12-04 20:25 ` [RFC 00/11] Make reference pruning more configurable Junio C Hamano
11 siblings, 0 replies; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 5:44 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Michael Haggerty
Add two new configuration settings,
fetch.pruneRef
remote.<name>.pruneRef
via which prune patterns (i.e., the equivalent of --prune=<pattern>)
can be configured globally or for particular remotes. The default
remains the same, namely "*".
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
Documentation/config.txt | 28 ++++++++++++++-----
Documentation/fetch-options.txt | 7 +++++
Documentation/git-remote.txt | 13 +++++----
remote.c | 47 +++++++++++++++++++++-----------
remote.h | 1 +
t/t5505-remote.sh | 60 +++++++++++++++++++++++++++++++++++++++++
t/t5510-fetch.sh | 13 +++++++++
7 files changed, 143 insertions(+), 26 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index a405806..5a2118e 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1069,6 +1069,14 @@ fetch.prune::
If true, fetch will automatically behave as if the `--prune`
option was given on the command line. See also `remote.<name>.prune`.
+fetch.pruneRef::
+ Glob pattern matching the names of local references that are
+ subject to pruning when "git fetch --prune" or "git remote
+ prune" is run for this remote. See the `--prune=<pattern>`
+ option to the linkgit:git-fetch[1] command for more
+ information. This setting may be overridden for particular
+ remotes via remote.<name>.pruneRef.
+
format.attach::
Enable multipart/mixed attachments as the default for
'format-patch'. The value can also be a double quoted string
@@ -2047,6 +2055,20 @@ remote.<name>.fetch::
The default set of "refspec" for linkgit:git-fetch[1]. See
linkgit:git-fetch[1].
+remote.<name>.prune::
+ When set to true, fetching from this remote by default will
+ also remove any remote-tracking references that no longer
+ exist on the remote (as if the `--prune` option were given on
+ the command line). Overrides `fetch.prune` settings, if any.
+ See also `remote.<name>.pruneRef`.
+
+remote.<name>.pruneRef::
+ Glob pattern matching the names of local references that are
+ subject to pruning when "git fetch --prune" or "git remote
+ prune" is run for this remote. See the `--prune=<pattern>`
+ option to the linkgit:git-fetch[1] command for more
+ information. This option overrides `fetch.pruneRef`.
+
remote.<name>.push::
The default set of "refspec" for linkgit:git-push[1]. See
linkgit:git-push[1].
@@ -2085,12 +2107,6 @@ remote.<name>.vcs::
Setting this to a value <vcs> will cause Git to interact with
the remote with the git-remote-<vcs> helper.
-remote.<name>.prune::
- When set to true, fetching from this remote by default will also
- remove any remote-tracking references that no longer exist on the
- remote (as if the `--prune` option was given on the command line).
- Overrides `fetch.prune` settings, if any.
-
remotes.<group>::
The list of remotes which are fetched by "git remote update
<group>". See linkgit:git-remote[1].
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 61d3f75..fa2cfdb 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -41,6 +41,7 @@ ifndef::git-pull[]
-p::
--prune[=<pattern>]::
+--no-prune::
After fetching, remove any remote-tracking references that no
longer exist on the remote. Tags are not subject to pruning
if they are fetched only because of the default tag
@@ -53,6 +54,12 @@ ifndef::git-pull[]
If pattern is specified, then it should be a glob pattern, and pruning
is further restricted to references whose names match the pattern.
This option can be specified multiple times.
++
+The default for `--prune`/`--no-prune` is taken from the configuration
+settings remote.<name>.prune or fetch.prune, or false if neither of
+these is set. The default pattern is taken from
+remote.<name>.pruneRef or fetch.pruneRef, or "*" if neither of these
+is set.
endif::git-pull[]
ifndef::git-pull[]
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index dd48474..4e1f8b2 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -151,17 +151,20 @@ With `--prune`, display stale remote-tracking branches that no longer
exist on the remote (this is the default). With `--prune=<pattern>`,
only report stale references whose names match <pattern> (this option
can be used multiple times). With `--no-prune`, do not report stale
-remote-tracking references at all.
+remote-tracking references at all. See linkgit:git-fetch[1] for more
+information about how pruning patterns can be configured.
+
With `-n` option, the remote heads are not queried first with
`git ls-remote <name>`; cached information is used instead.
'prune'::
-Deletes all stale remote-tracking branches under <name>.
-These stale branches have already been removed from the remote repository
-referenced by <name>, but are still locally available in
-"remotes/<name>".
+Delete all stale remote-tracking branches for the specified remote(s).
+Stale remote-tracking branches are those that have already been
+deleted from the remote repository referenced by <name>, but are still
+present in the local repository (typically under
+"refs/remotes/<name>"). See linkgit:git-fetch[1] for more information
+about pruning and how it can be configured.
+
With `--prune=<pattern>`, only prune references whose names match
pattern. This option can be used multiple times.
diff --git a/remote.c b/remote.c
index 89c9eaa..cc7f8d6 100644
--- a/remote.c
+++ b/remote.c
@@ -79,44 +79,58 @@ int prune_option_parse(const struct option *opt, const char *arg, int unset)
static int git_fetch_config(const char *k, const char *v, void *cb)
{
- int *fetch_prune_config = cb;
+ struct prune_option *prune_option = cb;
if (!strcmp(k, "fetch.prune")) {
- *fetch_prune_config = git_config_bool(k, v);
+ prune_option->prune = git_config_bool(k, v);
+ return 0;
+ } else if (!strcmp(k, "fetch.pruneref")) {
+ string_list_append(&prune_option->prune_patterns, v);
return 0;
}
return 0;
}
+static struct prune_option global_prune_option = PRUNE_OPTION_INIT;
+static int global_prune_option_read = 0;
+
void prune_option_fill(struct remote *remote,
struct prune_option *prune_option, int default_prune)
{
+ if (!global_prune_option_read) {
+ git_config(git_fetch_config, &global_prune_option);
+ global_prune_option_read = 1;
+ }
+
if (prune_option->prune < 0) {
/*
* The user specified neither --prune nor --no-prune;
* use the configured value of remote.<name>.prune or
* fetch.prune:
*/
- if (remote->prune >= 0) {
+ if (remote->prune >= 0)
prune_option->prune = remote->prune;
- } else {
- int fetch_prune_config = -1;
-
- git_config(git_fetch_config, &fetch_prune_config);
-
- if (fetch_prune_config >= 0)
- prune_option->prune = fetch_prune_config;
- else
- prune_option->prune = default_prune;
- }
+ else if (global_prune_option.prune >= 0)
+ prune_option->prune = global_prune_option.prune;
+ else
+ prune_option->prune = default_prune;
}
if (prune_option->prune && !prune_option->prune_patterns.nr) {
/*
* We want to prune, but no pruning patterns were
- * specified on the command line. Default to "*".
+ * specified on the command line. Use the value from
+ * remote.<name>.pruneRef or fetch.pruneRef if
+ * available; otherwise, default to "*".
*/
- string_list_append(&prune_option->prune_patterns, "*");
+ if (remote->prune_patterns.nr)
+ string_list_append_list(&prune_option->prune_patterns,
+ &remote->prune_patterns);
+ else if (global_prune_option.prune_patterns.nr)
+ string_list_append_list(&prune_option->prune_patterns,
+ &global_prune_option.prune_patterns);
+ else
+ string_list_append(&prune_option->prune_patterns, "*");
}
}
@@ -234,6 +248,7 @@ static struct remote *make_remote(const char *name, int len)
ret = xcalloc(1, sizeof(struct remote));
ret->prune = -1; /* unspecified */
+ ret->prune_patterns.strdup_strings = 1;
ALLOC_GROW(remotes, remotes_nr + 1, remotes_alloc);
remotes[remotes_nr++] = ret;
if (len)
@@ -492,6 +507,8 @@ static int handle_config(const char *key, const char *value, void *cb)
remote->skip_default_update = git_config_bool(key, value);
else if (!strcmp(subkey, ".prune"))
remote->prune = git_config_bool(key, value);
+ else if (!strcmp(subkey, ".pruneref"))
+ string_list_append(&remote->prune_patterns, value);
else if (!strcmp(subkey, ".url")) {
const char *v;
if (git_config_string(&v, key, value))
diff --git a/remote.h b/remote.h
index a484290..503c5c8 100644
--- a/remote.h
+++ b/remote.h
@@ -44,6 +44,7 @@ struct remote {
int skip_default_update;
int mirror;
int prune;
+ struct string_list prune_patterns;
const char *receivepack;
const char *uploadpack;
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index e156174..e6e0abe 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -258,6 +258,36 @@ test_expect_success 'prune with --prune' '
)
'
+test_expect_success 'prune with remote pruneRef config' '
+ git clone one prune-remote-config &&
+ (
+ cd prune-remote-config &&
+ # This first setting should not matter:
+ git config fetch.pruneRef "*" &&
+ git config remote.origin.pruneRef "refs/remotes/*1" &&
+ git update-ref refs/remotes/origin/branch1 master &&
+ git update-ref refs/remotes/origin/branch2 master &&
+
+ git remote prune origin &&
+ test_must_fail git rev-parse origin/branch1 &&
+ git rev-parse origin/branch2
+ )
+'
+
+test_expect_success 'prune with global pruneRef config' '
+ git clone one prune-global-config &&
+ (
+ cd prune-global-config &&
+ git config fetch.pruneRef "refs/remotes/*1" &&
+ git update-ref refs/remotes/origin/branch1 master &&
+ git update-ref refs/remotes/origin/branch2 master &&
+
+ git remote prune origin &&
+ test_must_fail git rev-parse origin/branch1 &&
+ git rev-parse origin/branch2
+ )
+'
+
test_expect_success 'set-head --delete' '
(
cd test &&
@@ -642,6 +672,36 @@ test_expect_success 'update --prune with argument' '
)
'
+test_expect_success 'update --prune with remote pruneRef config' '
+ git clone one update-prune-remote-config &&
+ (
+ cd update-prune-remote-config &&
+ # This first setting should not matter:
+ git config fetch.pruneRef "*" &&
+ git config remote.origin.pruneRef "refs/remotes/*1" &&
+ git update-ref refs/remotes/origin/branch1 master &&
+ git update-ref refs/remotes/origin/branch2 master &&
+
+ git remote update --prune origin &&
+ test_must_fail git rev-parse origin/branch1 &&
+ git rev-parse origin/branch2
+ )
+'
+
+test_expect_success 'update --prune with global pruneRef config' '
+ git clone one update-prune-global-config &&
+ (
+ cd update-prune-global-config &&
+ git config fetch.pruneRef "refs/remotes/*1" &&
+ git update-ref refs/remotes/origin/branch1 master &&
+ git update-ref refs/remotes/origin/branch2 master &&
+
+ git remote update --prune origin &&
+ test_must_fail git rev-parse origin/branch1 &&
+ git rev-parse origin/branch2
+ )
+'
+
cat >one/expect <<-\EOF
apis/master
apis/side
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index 42eb21f..c82b929 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -94,6 +94,19 @@ test_expect_success 'fetch --prune on its own works as expected' '
test_must_fail git rev-parse origin/extrabranch
'
+test_expect_success 'fetch with pruneRef config' '
+ cd "$D" &&
+ git clone . prune-config &&
+ cd prune-config &&
+ git config remote.origin.pruneRef "refs/remotes/*1" &&
+ git update-ref refs/remotes/origin/branch1 master &&
+ git update-ref refs/remotes/origin/branch2 master &&
+
+ git fetch --prune origin &&
+ test_must_fail git rev-parse origin/branch1 &&
+ git rev-parse origin/branch2
+'
+
test_expect_success 'fetch --prune with arguments' '
cd "$D" &&
git clone . prune-args &&
--
1.8.4.3
^ permalink raw reply related [flat|nested] 15+ messages in thread
* Re: [RFC 02/11] remote.c: add infrastructure for parsing --prune options
2013-12-04 5:44 ` [RFC 02/11] remote.c: add infrastructure for parsing --prune options Michael Haggerty
@ 2013-12-04 12:57 ` Duy Nguyen
2013-12-04 17:04 ` Michael Haggerty
0 siblings, 1 reply; 15+ messages in thread
From: Duy Nguyen @ 2013-12-04 12:57 UTC (permalink / raw)
To: Michael Haggerty; +Cc: Git Mailing List, Junio C Hamano
On Wed, Dec 4, 2013 at 12:44 PM, Michael Haggerty <mhagger@alum.mit.edu> wrote:
> +void argv_push_prune_option(struct argv_array *argv,
> + struct prune_option *prune_option)
> +{
> + if (prune_option->prune != -1)
> + argv_array_pushf(argv,
> + prune_option->prune
> + ? "--prune"
> + : "--no-prune");
> +}
Nit. I think argv_array_push() is enough for this case?
--
Duy
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RFC 02/11] remote.c: add infrastructure for parsing --prune options
2013-12-04 12:57 ` Duy Nguyen
@ 2013-12-04 17:04 ` Michael Haggerty
0 siblings, 0 replies; 15+ messages in thread
From: Michael Haggerty @ 2013-12-04 17:04 UTC (permalink / raw)
To: Duy Nguyen; +Cc: Git Mailing List, Junio C Hamano
On 12/04/2013 01:57 PM, Duy Nguyen wrote:
> On Wed, Dec 4, 2013 at 12:44 PM, Michael Haggerty <mhagger@alum.mit.edu> wrote:
>> +void argv_push_prune_option(struct argv_array *argv,
>> + struct prune_option *prune_option)
>> +{
>> + if (prune_option->prune != -1)
>> + argv_array_pushf(argv,
>> + prune_option->prune
>> + ? "--prune"
>> + : "--no-prune");
>> +}
>
> Nit. I think argv_array_push() is enough for this case?
Yes, you're right. Thanks for noticing.
If people want this patch series I will fix the problem in the next round.
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [RFC 00/11] Make reference pruning more configurable
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
` (10 preceding siblings ...)
2013-12-04 5:44 ` [RFC 11/11] remote: allow prune patterns to be configured Michael Haggerty
@ 2013-12-04 20:25 ` Junio C Hamano
11 siblings, 0 replies; 15+ messages in thread
From: Junio C Hamano @ 2013-12-04 20:25 UTC (permalink / raw)
To: Michael Haggerty; +Cc: git
Michael Haggerty <mhagger@alum.mit.edu> writes:
> But even though "--prune=<pattern>" is no longer needed to prevent tag
> nuking, it might be useful to somebody for other purposes, and
> therefore I am submitting it to the list as an RFC. Maybe there is a
> use case associated with non-branch, non-tag references, like perhaps
> Gerrit pull request-related references?
>
> Personally, I am -0 on this series. I think it adds more complication
> (code, documentation, etc) than its usefulness justifies.
I tend to agree. Even though selective "only prune these if the
other side no longer have corresponding refs" sounds like a great
flexibility as a concept, the user needs to know that the local refs
that match given patterns cannot come from remotes other than the
one that fetch is talking with, which is already too complicated for
the human user to grok ;-) "Don't mix refs from different sources in
a random hierarchy" is probably a good advice and when adhered to
there is no need for such a selective pruning.
> So, if anybody can think of a compelling use case for this feature,
> please make your case!
Thanks.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2013-12-04 20:25 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-04 5:44 [RFC 00/11] Make reference pruning more configurable Michael Haggerty
2013-12-04 5:44 ` [RFC 01/11] get_stale_heads(): allow limiting to refname patterns Michael Haggerty
2013-12-04 5:44 ` [RFC 02/11] remote.c: add infrastructure for parsing --prune options Michael Haggerty
2013-12-04 12:57 ` Duy Nguyen
2013-12-04 17:04 ` Michael Haggerty
2013-12-04 5:44 ` [RFC 03/11] fetch: use the new functions for handling " Michael Haggerty
2013-12-04 5:44 ` [RFC 04/11] remote: " Michael Haggerty
2013-12-04 5:44 ` [RFC 05/11] remote.c: add infrastructure to handle --prune=<pattern> Michael Haggerty
2013-12-04 5:44 ` [RFC 06/11] fetch --prune: allow refname patterns to be specified Michael Haggerty
2013-12-04 5:44 ` [RFC 07/11] remote update " Michael Haggerty
2013-12-04 5:44 ` [RFC 08/11] string_list_append_list(): new function Michael Haggerty
2013-12-04 5:44 ` [RFC 09/11] remote prune: allow --prune=<pattern> options Michael Haggerty
2013-12-04 5:44 ` [RFC 10/11] remote show: " Michael Haggerty
2013-12-04 5:44 ` [RFC 11/11] remote: allow prune patterns to be configured Michael Haggerty
2013-12-04 20:25 ` [RFC 00/11] Make reference pruning more configurable Junio C Hamano
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).