summaryrefslogtreecommitdiff
path: root/src/checkout.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/checkout.c')
-rw-r--r--src/checkout.c90
1 files changed, 49 insertions, 41 deletions
diff --git a/src/checkout.c b/src/checkout.c
index 52a076da6..3f65a9ed7 100644
--- a/src/checkout.c
+++ b/src/checkout.c
@@ -28,6 +28,11 @@
#include "buf_text.h"
#include "merge_file.h"
#include "path.h"
+#include "attr.h"
+#include "pool.h"
+#include "strmap.h"
+
+GIT__USE_STRMAP;
/* See docs/checkout-internals.md for more information */
@@ -68,7 +73,8 @@ typedef struct {
size_t total_steps;
size_t completed_steps;
git_checkout_perfdata perfdata;
- git_buf last_mkdir;
+ git_strmap *mkdir_map;
+ git_attr_session attr_session;
} checkout_data;
typedef struct {
@@ -1291,25 +1297,6 @@ fail:
return error;
}
-static int checkout_mkdir(
- checkout_data *data,
- const char *path,
- const char *base,
- mode_t mode,
- unsigned int flags)
-{
- struct git_futils_mkdir_perfdata mkdir_perfdata = {0};
-
- int error = git_futils_mkdir_withperf(
- path, base, mode, flags, &mkdir_perfdata);
-
- data->perfdata.mkdir_calls += mkdir_perfdata.mkdir_calls;
- data->perfdata.stat_calls += mkdir_perfdata.stat_calls;
- data->perfdata.chmod_calls += mkdir_perfdata.chmod_calls;
-
- return error;
-}
-
static bool should_remove_existing(checkout_data *data)
{
int ignorecase = 0;
@@ -1325,31 +1312,43 @@ static bool should_remove_existing(checkout_data *data)
#define MKDIR_REMOVE_EXISTING \
MKDIR_NORMAL | GIT_MKDIR_REMOVE_FILES | GIT_MKDIR_REMOVE_SYMLINKS
+static int checkout_mkdir(
+ checkout_data *data,
+ const char *path,
+ const char *base,
+ mode_t mode,
+ unsigned int flags)
+{
+ struct git_futils_mkdir_options mkdir_opts = {0};
+ int error;
+
+ mkdir_opts.dir_map = data->mkdir_map;
+ mkdir_opts.pool = &data->pool;
+
+ error = git_futils_mkdir_ext(
+ path, base, mode, flags, &mkdir_opts);
+
+ data->perfdata.mkdir_calls += mkdir_opts.perfdata.mkdir_calls;
+ data->perfdata.stat_calls += mkdir_opts.perfdata.stat_calls;
+ data->perfdata.chmod_calls += mkdir_opts.perfdata.chmod_calls;
+
+ return error;
+}
+
static int mkpath2file(
checkout_data *data, const char *path, unsigned int mode)
{
- git_buf *mkdir_path = &data->tmp;
struct stat st;
bool remove_existing = should_remove_existing(data);
+ unsigned int flags =
+ (remove_existing ? MKDIR_REMOVE_EXISTING : MKDIR_NORMAL) |
+ GIT_MKDIR_SKIP_LAST;
int error;
- if ((error = git_buf_sets(mkdir_path, path)) < 0)
+ if ((error = checkout_mkdir(
+ data, path, data->opts.target_directory, mode, flags)) < 0)
return error;
- git_buf_rtruncate_at_char(mkdir_path, '/');
-
- if (!data->last_mkdir.size ||
- data->last_mkdir.size != mkdir_path->size ||
- memcmp(mkdir_path->ptr, data->last_mkdir.ptr, mkdir_path->size) != 0) {
-
- if ((error = checkout_mkdir(
- data, mkdir_path->ptr, data->opts.target_directory, mode,
- remove_existing ? MKDIR_REMOVE_EXISTING : MKDIR_NORMAL)) < 0)
- return error;
-
- git_buf_swap(&data->last_mkdir, mkdir_path);
- }
-
if (remove_existing) {
data->perfdata.stat_calls++;
@@ -1425,8 +1424,8 @@ static int blob_content_to_file(
hint_path = path;
if (!data->opts.disable_filters)
- error = git_filter_list_load(
- &fl, git_blob_owner(blob), blob, hint_path,
+ error = git_filter_list__load_with_attr_session(
+ &fl, data->repo, &data->attr_session, blob, hint_path,
GIT_FILTER_TO_WORKTREE, GIT_FILTER_OPT_DEFAULT);
if (!error)
@@ -2008,7 +2007,8 @@ static int checkout_write_merge(
in_data.ptr = (char *)result.ptr;
in_data.size = result.len;
- if ((error = git_filter_list_load(&fl, data->repo, NULL, git_buf_cstr(&path_workdir),
+ if ((error = git_filter_list__load_with_attr_session(
+ &fl, data->repo, &data->attr_session, NULL, git_buf_cstr(&path_workdir),
GIT_FILTER_TO_WORKTREE, GIT_FILTER_OPT_DEFAULT)) < 0 ||
(error = git_filter_list_apply_to_data(&out_data, fl, &in_data)) < 0)
goto done;
@@ -2212,12 +2212,17 @@ static void checkout_data_clear(checkout_data *data)
git__free(data->pfx);
data->pfx = NULL;
- git_buf_free(&data->last_mkdir);
+ git_strmap_free(data->mkdir_map);
+
git_buf_free(&data->path);
git_buf_free(&data->tmp);
git_index_free(data->index);
data->index = NULL;
+
+ git_strmap_free(data->mkdir_map);
+
+ git_attr_session__free(&data->attr_session);
}
static int checkout_data_init(
@@ -2355,11 +2360,14 @@ static int checkout_data_init(
(error = git_vector_init(&data->update_conflicts, 0, NULL)) < 0 ||
(error = git_pool_init(&data->pool, 1, 0)) < 0 ||
(error = git_buf_puts(&data->path, data->opts.target_directory)) < 0 ||
- (error = git_path_to_dir(&data->path)) < 0)
+ (error = git_path_to_dir(&data->path)) < 0 ||
+ (error = git_strmap_alloc(&data->mkdir_map)) < 0)
goto cleanup;
data->workdir_len = git_buf_len(&data->path);
+ git_attr_session__init(&data->attr_session, data->repo);
+
cleanup:
if (error < 0)
checkout_data_clear(data);