diff mbox series

[v2,4/7] merge-ort: add a handle_deferred_entries() helper function

Message ID 7e28323b624ad2d8d12123783f00f5a8fbb248e8.1626204784.git.gitgitgadget@gmail.com (mailing list archive)
State New, archived
Headers show
Series Optimization batch 14: trivial directory resolution | expand

Commit Message

Elijah Newren July 13, 2021, 7:33 p.m. UTC
From: Elijah Newren <newren@gmail.com>

In order to allow trivial directory resolution, we first need to be able
to gather more information to determine if the optimization is safe.  To
enable that, we need a way of deferring the recursion into the directory
until a later time.  Naturally, deferring the entry into a subtree means
that we need some function that will later recurse into the subdirectory
exactly the same way that collect_merge_info_callback() would have done.

Add a helper function that does this.  For now this function is not used
but a subsequent commit will change that.  Future commits will also make
the function sometimes resolve directories instead of traversing inside.

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 merge-ort.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

Comments

Derrick Stolee July 15, 2021, 2:32 p.m. UTC | #1
On 7/13/2021 3:33 PM, Elijah Newren via GitGitGadget wrote:
> From: Elijah Newren <newren@gmail.com>
> 
> In order to allow trivial directory resolution, we first need to be able
> to gather more information to determine if the optimization is safe.  To
> enable that, we need a way of deferring the recursion into the directory
> until a later time.  Naturally, deferring the entry into a subtree means
> that we need some function that will later recurse into the subdirectory
> exactly the same way that collect_merge_info_callback() would have done.
> 
> Add a helper function that does this.  For now this function is not used
> but a subsequent commit will change that.  Future commits will also make
> the function sometimes resolve directories instead of traversing inside.
...> +MAYBE_UNUSED
> +static int handle_deferred_entries(struct merge_options *opt,
> +				   struct traverse_info *info)
> +{
> +	struct rename_info *renames = &opt->priv->renames;
> +	struct hashmap_iter iter;
> +	struct strmap_entry *entry;
> +	int side, ret = 0;
> +
> +	for (side = MERGE_SIDE1; side <= MERGE_SIDE2; side++) {
> +		renames->trivial_merges_okay[side] = 0;

We are unconditionally setting this to zero? I will await the
use of the method to see how that affects things.

> +		strintmap_for_each_entry(&renames->possible_trivial_merges[side],
> +					 &iter, entry) {

The rest of this loop seems like standard logic for handling
these tree walks.

Thanks,
-Stolee
Elijah Newren July 15, 2021, 3:59 p.m. UTC | #2
On Thu, Jul 15, 2021 at 7:32 AM Derrick Stolee <stolee@gmail.com> wrote:
>
> On 7/13/2021 3:33 PM, Elijah Newren via GitGitGadget wrote:
> > From: Elijah Newren <newren@gmail.com>
> >
> > In order to allow trivial directory resolution, we first need to be able
> > to gather more information to determine if the optimization is safe.  To
> > enable that, we need a way of deferring the recursion into the directory
> > until a later time.  Naturally, deferring the entry into a subtree means
> > that we need some function that will later recurse into the subdirectory
> > exactly the same way that collect_merge_info_callback() would have done.
> >
> > Add a helper function that does this.  For now this function is not used
> > but a subsequent commit will change that.  Future commits will also make
> > the function sometimes resolve directories instead of traversing inside.
> ...> +MAYBE_UNUSED
> > +static int handle_deferred_entries(struct merge_options *opt,
> > +                                struct traverse_info *info)
> > +{
> > +     struct rename_info *renames = &opt->priv->renames;
> > +     struct hashmap_iter iter;
> > +     struct strmap_entry *entry;
> > +     int side, ret = 0;
> > +
> > +     for (side = MERGE_SIDE1; side <= MERGE_SIDE2; side++) {
> > +             renames->trivial_merges_okay[side] = 0;
>
> We are unconditionally setting this to zero? I will await the
> use of the method to see how that affects things.

Unconditionally set to 0 because at this point in the series we don't
yet have the logic to handle it.  This line will be replaced later
once we add the necessary logic.

>
> > +             strintmap_for_each_entry(&renames->possible_trivial_merges[side],
> > +                                      &iter, entry) {
>
> The rest of this loop seems like standard logic for handling
> these tree walks.
>
> Thanks,
> -Stolee
diff mbox series

Patch

diff --git a/merge-ort.c b/merge-ort.c
index 3d3f00b3b45..eb0e18d7546 100644
--- a/merge-ort.c
+++ b/merge-ort.c
@@ -1196,6 +1196,70 @@  static int collect_merge_info_callback(int n,
 	return mask;
 }
 
+MAYBE_UNUSED
+static int handle_deferred_entries(struct merge_options *opt,
+				   struct traverse_info *info)
+{
+	struct rename_info *renames = &opt->priv->renames;
+	struct hashmap_iter iter;
+	struct strmap_entry *entry;
+	int side, ret = 0;
+
+	for (side = MERGE_SIDE1; side <= MERGE_SIDE2; side++) {
+		renames->trivial_merges_okay[side] = 0;
+		strintmap_for_each_entry(&renames->possible_trivial_merges[side],
+					 &iter, entry) {
+			const char *path = entry->key;
+			unsigned dir_rename_mask = (intptr_t)entry->value;
+			struct conflict_info *ci;
+			unsigned dirmask;
+			struct tree_desc t[3];
+			void *buf[3] = {NULL,};
+			int i;
+
+			ci = strmap_get(&opt->priv->paths, path);
+			VERIFY_CI(ci);
+			dirmask = ci->dirmask;
+
+			info->name = path;
+			info->namelen = strlen(path);
+			info->pathlen = info->namelen + 1;
+
+			for (i = 0; i < 3; i++, dirmask >>= 1) {
+				if (i == 1 && ci->match_mask == 3)
+					t[1] = t[0];
+				else if (i == 2 && ci->match_mask == 5)
+					t[2] = t[0];
+				else if (i == 2 && ci->match_mask == 6)
+					t[2] = t[1];
+				else {
+					const struct object_id *oid = NULL;
+					if (dirmask & 1)
+						oid = &ci->stages[i].oid;
+					buf[i] = fill_tree_descriptor(opt->repo,
+								      t+i, oid);
+				}
+			}
+
+			ci->match_mask &= ci->filemask;
+			opt->priv->current_dir_name = path;
+			renames->dir_rename_mask = dir_rename_mask;
+			if (renames->dir_rename_mask == 0 ||
+			    renames->dir_rename_mask == 0x07)
+				ret = traverse_trees(NULL, 3, t, info);
+			else
+				ret = traverse_trees_wrapper(NULL, 3, t, info);
+
+			for (i = MERGE_BASE; i <= MERGE_SIDE2; i++)
+				free(buf[i]);
+
+			if (ret < 0)
+				return ret;
+		}
+	}
+	return ret;
+}
+
 static int collect_merge_info(struct merge_options *opt,
 			      struct tree *merge_base,
 			      struct tree *side1,