Re: [PATCH v6 40/42] refs.c: pass a skip list to name_conflict_fn

2014-05-02 Thread Ronnie Sahlberg
Fixed. Thanks.

On Thu, May 1, 2014 at 9:22 PM, Eric Sunshine sunsh...@sunshineco.com wrote:
 On Thu, May 1, 2014 at 4:37 PM, Ronnie Sahlberg sahlb...@google.com wrote:
 Allow passing a list of refs to ckip checking to name_conflict_fn.

 s/ckip/skip/

 There are some conditions where we want to allow a temporary conflict and 
 skip
 checking those refs. For example if we have a transaction that
 1, guarantees that m is a packed refs and there is no loose ref for m
 2, the transaction will delete m from the packed ref
 3, the transaction will create conflicting m/m

 For this case we want to be able to lock anc create m/m since we know that 
 the

 s/anc/and/

 conflict is only transient. I.e. the conflict will be automatically resolved
 by the transaction when it deletes m.

 Signed-off-by: Ronnie Sahlberg sahlb...@google.com
 ---
  refs.c | 43 +--
  1 file changed, 33 insertions(+), 10 deletions(-)

 diff --git a/refs.c b/refs.c
 index b525076..eb75927 100644
 --- a/refs.c
 +++ b/refs.c
 @@ -789,11 +789,19 @@ struct name_conflict_cb {
 const char *refname;
 const char *oldrefname;
 const char *conflicting_refname;
 +   const char **skip;
 +   int skipnum;
  };

  static int name_conflict_fn(struct ref_entry *entry, void *cb_data)
  {
 struct name_conflict_cb *data = (struct name_conflict_cb *)cb_data;
 +   int i;
 +   for(i = 0; i  data-skipnum; i++) {
 +   if (!strcmp(entry-name, data-skip[i])) {
 +   return 0;
 +   }
 +   }
 if (data-oldrefname  !strcmp(data-oldrefname, entry-name))
 return 0;
 if (names_conflict(data-refname, entry-name)) {
 @@ -808,15 +816,21 @@ static int name_conflict_fn(struct ref_entry *entry, 
 void *cb_data)
   * conflicting with the name of an existing reference in dir.  If
   * oldrefname is non-NULL, ignore potential conflicts with oldrefname
   * (e.g., because oldrefname is scheduled for deletion in the same
 - * operation).
 + * operation). skip contains a list of refs we want to skip checking for
 + * conflicts with. Refs may be skipped due to us knowing that it will
 + * be deleted later during a transaction that deletes one reference and then
 + * creates a new conflicting reference. For example a rename from m to m/m.
   */
  static int is_refname_available(const char *refname, const char *oldrefname,
 -   struct ref_dir *dir)
 +   struct ref_dir *dir,
 +   const char **skip, int skipnum)
  {
 struct name_conflict_cb data;
 data.refname = refname;
 data.oldrefname = oldrefname;
 data.conflicting_refname = NULL;
 +   data.skip = skip;
 +   data.skipnum = skipnum;

 sort_ref_dir(dir);
 if (do_for_each_entry_in_dir(dir, 0, name_conflict_fn, data)) {
 @@ -2032,7 +2046,8 @@ int dwim_log(const char *str, int len, unsigned char 
 *sha1, char **log)

  static struct ref_lock *lock_ref_sha1_basic(const char *refname,
 const unsigned char *old_sha1,
 -   int flags, int *type_p)
 +   int flags, int *type_p,
 +   const char **skip, int skipnum)
  {
 char *ref_file;
 const char *orig_refname = refname;
 @@ -2079,7 +2094,9 @@ static struct ref_lock *lock_ref_sha1_basic(const char 
 *refname,
  * name is a proper prefix of our refname.
  */
 if (missing 
 -!is_refname_available(refname, NULL, 
 get_packed_refs(ref_cache))) {
 +!is_refname_available(refname, NULL,
 +  get_packed_refs(ref_cache),
 +  skip, skipnum)) {
 last_errno = ENOTDIR;
 goto error_return;
 }
 @@ -2137,7 +2154,7 @@ struct ref_lock *lock_any_ref_for_update(const char 
 *refname,
  const unsigned char *old_sha1,
  int flags, int *type_p)
  {
 -   return lock_ref_sha1_basic(refname, old_sha1, flags, type_p);
 +   return lock_ref_sha1_basic(refname, old_sha1, flags, type_p, NULL, 
 0);
  }

  /*
 @@ -2576,6 +2593,9 @@ int rename_ref(const char *oldrefname, const char 
 *newrefname, const char *logms
 int log = !lstat(git_path(logs/%s, oldrefname), loginfo);
 const char *symref = NULL;

 +   if (!strcmp(oldrefname, newrefname))
 +   return 0;
 +
 if (log  S_ISLNK(loginfo.st_mode))
 return error(reflog for %s is a symlink, oldrefname);

 @@ -2586,10 +2606,12 @@ int rename_ref(const char *oldrefname, const char 
 *newrefname, const char *logms
 if (!symref)
 return error(refname %s not found, oldrefname);

 -   if 

[PATCH v6 40/42] refs.c: pass a skip list to name_conflict_fn

2014-05-01 Thread Ronnie Sahlberg
Allow passing a list of refs to ckip checking to name_conflict_fn.
There are some conditions where we want to allow a temporary conflict and skip
checking those refs. For example if we have a transaction that
1, guarantees that m is a packed refs and there is no loose ref for m
2, the transaction will delete m from the packed ref
3, the transaction will create conflicting m/m

For this case we want to be able to lock anc create m/m since we know that the
conflict is only transient. I.e. the conflict will be automatically resolved
by the transaction when it deletes m.

Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 refs.c | 43 +--
 1 file changed, 33 insertions(+), 10 deletions(-)

diff --git a/refs.c b/refs.c
index b525076..eb75927 100644
--- a/refs.c
+++ b/refs.c
@@ -789,11 +789,19 @@ struct name_conflict_cb {
const char *refname;
const char *oldrefname;
const char *conflicting_refname;
+   const char **skip;
+   int skipnum;
 };
 
 static int name_conflict_fn(struct ref_entry *entry, void *cb_data)
 {
struct name_conflict_cb *data = (struct name_conflict_cb *)cb_data;
+   int i;
+   for(i = 0; i  data-skipnum; i++) {
+   if (!strcmp(entry-name, data-skip[i])) {
+   return 0;
+   }
+   }
if (data-oldrefname  !strcmp(data-oldrefname, entry-name))
return 0;
if (names_conflict(data-refname, entry-name)) {
@@ -808,15 +816,21 @@ static int name_conflict_fn(struct ref_entry *entry, void 
*cb_data)
  * conflicting with the name of an existing reference in dir.  If
  * oldrefname is non-NULL, ignore potential conflicts with oldrefname
  * (e.g., because oldrefname is scheduled for deletion in the same
- * operation).
+ * operation). skip contains a list of refs we want to skip checking for
+ * conflicts with. Refs may be skipped due to us knowing that it will
+ * be deleted later during a transaction that deletes one reference and then
+ * creates a new conflicting reference. For example a rename from m to m/m.
  */
 static int is_refname_available(const char *refname, const char *oldrefname,
-   struct ref_dir *dir)
+   struct ref_dir *dir,
+   const char **skip, int skipnum)
 {
struct name_conflict_cb data;
data.refname = refname;
data.oldrefname = oldrefname;
data.conflicting_refname = NULL;
+   data.skip = skip;
+   data.skipnum = skipnum;
 
sort_ref_dir(dir);
if (do_for_each_entry_in_dir(dir, 0, name_conflict_fn, data)) {
@@ -2032,7 +2046,8 @@ int dwim_log(const char *str, int len, unsigned char 
*sha1, char **log)
 
 static struct ref_lock *lock_ref_sha1_basic(const char *refname,
const unsigned char *old_sha1,
-   int flags, int *type_p)
+   int flags, int *type_p,
+   const char **skip, int skipnum)
 {
char *ref_file;
const char *orig_refname = refname;
@@ -2079,7 +2094,9 @@ static struct ref_lock *lock_ref_sha1_basic(const char 
*refname,
 * name is a proper prefix of our refname.
 */
if (missing 
-!is_refname_available(refname, NULL, get_packed_refs(ref_cache))) 
{
+!is_refname_available(refname, NULL,
+  get_packed_refs(ref_cache),
+  skip, skipnum)) {
last_errno = ENOTDIR;
goto error_return;
}
@@ -2137,7 +2154,7 @@ struct ref_lock *lock_any_ref_for_update(const char 
*refname,
 const unsigned char *old_sha1,
 int flags, int *type_p)
 {
-   return lock_ref_sha1_basic(refname, old_sha1, flags, type_p);
+   return lock_ref_sha1_basic(refname, old_sha1, flags, type_p, NULL, 0);
 }
 
 /*
@@ -2576,6 +2593,9 @@ int rename_ref(const char *oldrefname, const char 
*newrefname, const char *logms
int log = !lstat(git_path(logs/%s, oldrefname), loginfo);
const char *symref = NULL;
 
+   if (!strcmp(oldrefname, newrefname))
+   return 0;
+
if (log  S_ISLNK(loginfo.st_mode))
return error(reflog for %s is a symlink, oldrefname);
 
@@ -2586,10 +2606,12 @@ int rename_ref(const char *oldrefname, const char 
*newrefname, const char *logms
if (!symref)
return error(refname %s not found, oldrefname);
 
-   if (!is_refname_available(newrefname, oldrefname, 
get_packed_refs(ref_cache)))
+   if (!is_refname_available(newrefname, oldrefname,
+ get_packed_refs(ref_cache), NULL, 0))
return 1;
 
-   if (!is_refname_available(newrefname, oldrefname, 

Re: [PATCH v6 40/42] refs.c: pass a skip list to name_conflict_fn

2014-05-01 Thread Eric Sunshine
On Thu, May 1, 2014 at 4:37 PM, Ronnie Sahlberg sahlb...@google.com wrote:
 Allow passing a list of refs to ckip checking to name_conflict_fn.

s/ckip/skip/

 There are some conditions where we want to allow a temporary conflict and skip
 checking those refs. For example if we have a transaction that
 1, guarantees that m is a packed refs and there is no loose ref for m
 2, the transaction will delete m from the packed ref
 3, the transaction will create conflicting m/m

 For this case we want to be able to lock anc create m/m since we know that the

s/anc/and/

 conflict is only transient. I.e. the conflict will be automatically resolved
 by the transaction when it deletes m.

 Signed-off-by: Ronnie Sahlberg sahlb...@google.com
 ---
  refs.c | 43 +--
  1 file changed, 33 insertions(+), 10 deletions(-)

 diff --git a/refs.c b/refs.c
 index b525076..eb75927 100644
 --- a/refs.c
 +++ b/refs.c
 @@ -789,11 +789,19 @@ struct name_conflict_cb {
 const char *refname;
 const char *oldrefname;
 const char *conflicting_refname;
 +   const char **skip;
 +   int skipnum;
  };

  static int name_conflict_fn(struct ref_entry *entry, void *cb_data)
  {
 struct name_conflict_cb *data = (struct name_conflict_cb *)cb_data;
 +   int i;
 +   for(i = 0; i  data-skipnum; i++) {
 +   if (!strcmp(entry-name, data-skip[i])) {
 +   return 0;
 +   }
 +   }
 if (data-oldrefname  !strcmp(data-oldrefname, entry-name))
 return 0;
 if (names_conflict(data-refname, entry-name)) {
 @@ -808,15 +816,21 @@ static int name_conflict_fn(struct ref_entry *entry, 
 void *cb_data)
   * conflicting with the name of an existing reference in dir.  If
   * oldrefname is non-NULL, ignore potential conflicts with oldrefname
   * (e.g., because oldrefname is scheduled for deletion in the same
 - * operation).
 + * operation). skip contains a list of refs we want to skip checking for
 + * conflicts with. Refs may be skipped due to us knowing that it will
 + * be deleted later during a transaction that deletes one reference and then
 + * creates a new conflicting reference. For example a rename from m to m/m.
   */
  static int is_refname_available(const char *refname, const char *oldrefname,
 -   struct ref_dir *dir)
 +   struct ref_dir *dir,
 +   const char **skip, int skipnum)
  {
 struct name_conflict_cb data;
 data.refname = refname;
 data.oldrefname = oldrefname;
 data.conflicting_refname = NULL;
 +   data.skip = skip;
 +   data.skipnum = skipnum;

 sort_ref_dir(dir);
 if (do_for_each_entry_in_dir(dir, 0, name_conflict_fn, data)) {
 @@ -2032,7 +2046,8 @@ int dwim_log(const char *str, int len, unsigned char 
 *sha1, char **log)

  static struct ref_lock *lock_ref_sha1_basic(const char *refname,
 const unsigned char *old_sha1,
 -   int flags, int *type_p)
 +   int flags, int *type_p,
 +   const char **skip, int skipnum)
  {
 char *ref_file;
 const char *orig_refname = refname;
 @@ -2079,7 +2094,9 @@ static struct ref_lock *lock_ref_sha1_basic(const char 
 *refname,
  * name is a proper prefix of our refname.
  */
 if (missing 
 -!is_refname_available(refname, NULL, 
 get_packed_refs(ref_cache))) {
 +!is_refname_available(refname, NULL,
 +  get_packed_refs(ref_cache),
 +  skip, skipnum)) {
 last_errno = ENOTDIR;
 goto error_return;
 }
 @@ -2137,7 +2154,7 @@ struct ref_lock *lock_any_ref_for_update(const char 
 *refname,
  const unsigned char *old_sha1,
  int flags, int *type_p)
  {
 -   return lock_ref_sha1_basic(refname, old_sha1, flags, type_p);
 +   return lock_ref_sha1_basic(refname, old_sha1, flags, type_p, NULL, 0);
  }

  /*
 @@ -2576,6 +2593,9 @@ int rename_ref(const char *oldrefname, const char 
 *newrefname, const char *logms
 int log = !lstat(git_path(logs/%s, oldrefname), loginfo);
 const char *symref = NULL;

 +   if (!strcmp(oldrefname, newrefname))
 +   return 0;
 +
 if (log  S_ISLNK(loginfo.st_mode))
 return error(reflog for %s is a symlink, oldrefname);

 @@ -2586,10 +2606,12 @@ int rename_ref(const char *oldrefname, const char 
 *newrefname, const char *logms
 if (!symref)
 return error(refname %s not found, oldrefname);

 -   if (!is_refname_available(newrefname, oldrefname, 
 get_packed_refs(ref_cache)))
 +   if