static void assert_sm_valid(git_repository *parent, git_repository *child, const char *sm_name) { git_buf expected = GIT_BUF_INIT, actual = GIT_BUF_INIT; /* assert working directory */ cl_git_pass(git_buf_joinpath(&expected, git_repository_workdir(parent), sm_name)); cl_git_pass(git_path_prettify_dir(&expected, expected.ptr, NULL)); cl_git_pass(git_buf_sets(&actual, git_repository_workdir(child))); cl_git_pass(git_path_prettify_dir(&actual, actual.ptr, NULL)); cl_assert_equal_s(expected.ptr, actual.ptr); git_buf_clear(&expected); git_buf_clear(&actual); /* assert common directory */ cl_git_pass(git_buf_joinpath(&expected, git_repository_commondir(parent), "modules")); cl_git_pass(git_buf_joinpath(&expected, expected.ptr, sm_name)); cl_git_pass(git_path_prettify_dir(&expected, expected.ptr, NULL)); cl_git_pass(git_buf_sets(&actual, git_repository_commondir(child))); cl_git_pass(git_path_prettify_dir(&actual, actual.ptr, NULL)); cl_assert_equal_s(expected.ptr, actual.ptr); /* assert git directory */ cl_git_pass(git_buf_sets(&actual, git_repository_path(child))); cl_git_pass(git_path_prettify_dir(&actual, actual.ptr, NULL)); cl_assert_equal_s(expected.ptr, actual.ptr); git_buf_dispose(&expected); git_buf_dispose(&actual); }
int git_futils_find_system_file(git_buf *path, const char *filename) { #ifdef GIT_WIN32 struct win32_path root; if (win32_expand_path(&root, L"%PROGRAMFILES%\\Git\\etc\\") < 0 || root.path[0] == L'%') /* i.e. no expansion happened */ { giterr_set(GITERR_OS, "Cannot locate the system's Program Files directory"); return -1; } if (win32_find_file(path, &root, filename) < 0) { git_buf_clear(path); return GIT_ENOTFOUND; } return 0; #else if (git_buf_joinpath(path, "/etc", filename) < 0) return -1; if (git_path_exists(path->ptr) == true) return 0; git_buf_clear(path); return GIT_ENOTFOUND; #endif }
int git_futils_find_global_file(git_buf *path, const char *filename) { #ifdef GIT_WIN32 struct win32_path root; static const wchar_t *tmpls[4] = { L"%HOME%\\", L"%HOMEDRIVE%%HOMEPATH%\\", L"%USERPROFILE%\\", NULL, }; const wchar_t **tmpl; for (tmpl = tmpls; *tmpl != NULL; tmpl++) { /* try to expand environment variable, skipping if not set */ if (win32_expand_path(&root, *tmpl) != 0 || root.path[0] == L'%') continue; /* try to look up file under path */ if (!win32_find_file(path, &root, filename)) return 0; /* No error if file not found under %HOME%, b/c we don't trust it, * but do error if another var is set and yet file is not found. */ if (tmpl != tmpls) break; } giterr_set(GITERR_OS, "The global file '%s' doesn't exist", filename); git_buf_clear(path); return GIT_ENOTFOUND; #else const char *home = getenv("HOME"); if (home == NULL) { giterr_set(GITERR_OS, "Global file lookup failed. " "Cannot locate the user's home directory"); return GIT_ENOTFOUND; } if (git_buf_joinpath(path, home, filename) < 0) return -1; if (git_path_exists(path->ptr) == false) { giterr_set(GITERR_OS, "The global file '%s' doesn't exist", filename); git_buf_clear(path); return GIT_ENOTFOUND; } return 0; #endif }
void test_config_new__write_new_config(void) { git_config *config; git_buf buf = GIT_BUF_INIT; cl_git_mkfile(TEST_CONFIG, ""); cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); cl_git_pass(git_config_set_string(config, "color.ui", "auto")); cl_git_pass(git_config_set_string(config, "core.editor", "ed")); git_config_free(config); cl_git_pass(git_config_open_ondisk(&config, TEST_CONFIG)); cl_git_pass(git_config_get_string_buf(&buf, config, "color.ui")); cl_assert_equal_s("auto", git_buf_cstr(&buf)); git_buf_clear(&buf); cl_git_pass(git_config_get_string_buf(&buf, config, "core.editor")); cl_assert_equal_s("ed", git_buf_cstr(&buf)); git_buf_free(&buf); git_config_free(config); p_unlink(TEST_CONFIG); }
int merge_commits_from_branches( git_index **index, git_repository *repo, const char *ours_name, const char *theirs_name, git_merge_options *opts) { git_commit *our_commit, *their_commit; git_oid our_oid, their_oid; git_buf branch_buf = GIT_BUF_INIT; git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours_name); cl_git_pass(git_reference_name_to_id(&our_oid, repo, branch_buf.ptr)); cl_git_pass(git_commit_lookup(&our_commit, repo, &our_oid)); git_buf_clear(&branch_buf); git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs_name); cl_git_pass(git_reference_name_to_id(&their_oid, repo, branch_buf.ptr)); cl_git_pass(git_commit_lookup(&their_commit, repo, &their_oid)); cl_git_pass(git_merge_commits(index, repo, our_commit, their_commit, opts)); git_buf_free(&branch_buf); git_commit_free(our_commit); git_commit_free(their_commit); return 0; }
static int merge_trivial(const char *ours, const char *theirs, bool automerge) { git_buf branch_buf = GIT_BUF_INIT; git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; git_reference *our_ref, *their_ref; git_merge_head *their_heads[1]; git_merge_opts opts = GIT_MERGE_OPTS_INIT; git_merge_result *result; checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; opts.merge_tree_opts.automerge_flags |= automerge ? 0 : GIT_MERGE_AUTOMERGE_NONE; git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, ours); cl_git_pass(git_reference_symbolic_create(&our_ref, repo, "HEAD", branch_buf.ptr, 1)); cl_git_pass(git_checkout_head(repo, &checkout_opts)); git_buf_clear(&branch_buf); git_buf_printf(&branch_buf, "%s%s", GIT_REFS_HEADS_DIR, theirs); cl_git_pass(git_reference_lookup(&their_ref, repo, branch_buf.ptr)); cl_git_pass(git_merge_head_from_ref(&their_heads[0], repo, their_ref)); cl_git_pass(git_merge(&result, repo, (const git_merge_head **)their_heads, 1, &opts)); git_buf_free(&branch_buf); git_reference_free(our_ref); git_reference_free(their_ref); git_merge_head_free(their_heads[0]); git_merge_result_free(result); return 0; }
int git_buf_text_common_prefix(git_buf *buf, const git_strarray *strings) { size_t i; const char *str, *pfx; git_buf_clear(buf); if (!strings || !strings->count) return 0; /* initialize common prefix to first string */ if (git_buf_sets(buf, strings->strings[0]) < 0) return -1; /* go through the rest of the strings, truncating to shared prefix */ for (i = 1; i < strings->count; ++i) { for (str = strings->strings[i], pfx = buf->ptr; *str && *str == *pfx; str++, pfx++) /* scanning */; git_buf_truncate(buf, pfx - buf->ptr); if (!buf->size) break; } return 0; }
int git_path_prettify(git_buf *path_out, const char *path, const char *base) { char *result = NULL; int error = GIT_SUCCESS; git_buf_clear(path_out); /* construct path if needed */ if (base != NULL && git_path_root(path) < 0) { if ((error = git_buf_joinpath(path_out, base, path)) < GIT_SUCCESS) return error; path = path_out->ptr; } /* allow realpath to allocate the buffer */ if (path != NULL) result = p_realpath(path, NULL); if (result) { error = git_buf_sets(path_out, result); git__free(result); } else { error = GIT_EOSERR; } return error; }
static void stage_content(char *content[]) { git_reference *head; git_object *head_object; git_buf path = GIT_BUF_INIT; char *filename, *text; size_t i; cl_git_pass(git_repository_head(&head, repo)); cl_git_pass(git_reference_peel(&head_object, head, GIT_OBJ_COMMIT)); cl_git_pass(git_reset(repo, head_object, GIT_RESET_HARD, NULL)); for (i = 0, filename = content[i], text = content[++i]; filename && text; filename = content[++i], text = content[++i]) { git_buf_clear(&path); cl_git_pass(git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename)); cl_git_mkfile(path.ptr, text); cl_git_pass(git_index_add_bypath(repo_index, filename)); } git_object_free(head_object); git_reference_free(head); git_buf_free(&path); }
static int diff_print_patch_line( const git_diff_delta *delta, const git_diff_range *range, char line_origin, /* GIT_DIFF_LINE value from above */ const char *content, size_t content_len, void *data) { diff_print_info *pi = data; if (S_ISDIR(delta->new_file.mode)) return 0; git_buf_clear(pi->buf); if (line_origin == GIT_DIFF_LINE_ADDITION || line_origin == GIT_DIFF_LINE_DELETION || line_origin == GIT_DIFF_LINE_CONTEXT) git_buf_printf(pi->buf, "%c%.*s", line_origin, (int)content_len, content); else if (content_len > 0) git_buf_printf(pi->buf, "%.*s", (int)content_len, content); if (git_buf_oom(pi->buf)) return -1; if (pi->print_cb(delta, range, line_origin, git_buf_cstr(pi->buf), git_buf_len(pi->buf), pi->payload)) return callback_error(); return 0; }
int git_futils_readbuffer_fd(git_buf *buf, git_file fd, size_t len) { ssize_t read_size = 0; size_t alloc_len; git_buf_clear(buf); if (!git__is_ssizet(len)) { giterr_set(GITERR_INVALID, "read too large"); return -1; } GITERR_CHECK_ALLOC_ADD(&alloc_len, len, 1); if (git_buf_grow(buf, alloc_len) < 0) return -1; /* p_read loops internally to read len bytes */ read_size = p_read(fd, buf->ptr, len); if (read_size != (ssize_t)len) { giterr_set(GITERR_OS, "failed to read descriptor"); git_buf_free(buf); return -1; } buf->ptr[read_size] = '\0'; buf->size = read_size; return 0; }
/* Lots of empty dirs, or nearly empty ones, make the old workdir * iterator cry. Also, segfault. */ void test_iterator_workdir__filesystem_gunk(void) { git_iterator *i; git_buf parent = GIT_BUF_INIT; int n; if (!cl_is_env_set("GITTEST_INVASIVE_SPEED")) cl_skip(); g_repo = cl_git_sandbox_init("testrepo"); for (n = 0; n < 100000; n++) { git_buf_clear(&parent); git_buf_printf(&parent, "%s/refs/heads/foo/%d/subdir", git_repository_path(g_repo), n); cl_assert(!git_buf_oom(&parent)); cl_git_pass(git_futils_mkdir(parent.ptr, 0775, GIT_MKDIR_PATH)); } cl_git_pass(git_iterator_for_filesystem(&i, "testrepo/.git/refs", NULL)); /* should only have 13 items, since we're not asking for trees to be * returned. the goal of this test is simply to not crash. */ expect_iterator_items(i, 15, NULL, 15, NULL); git_iterator_free(i); git_buf_dispose(&parent); }
int git_path_make_relative(git_buf *path, const char *parent) { const char *p, *q, *p_dirsep, *q_dirsep; size_t plen = path->size, newlen, alloclen, depth = 1, i, offset; for (p_dirsep = p = path->ptr, q_dirsep = q = parent; *p && *q; p++, q++) { if (*p == '/' && *q == '/') { p_dirsep = p; q_dirsep = q; } else if (*p != *q) break; } /* need at least 1 common path segment */ if ((p_dirsep == path->ptr || q_dirsep == parent) && (*p_dirsep != '/' || *q_dirsep != '/')) { giterr_set(GITERR_INVALID, "%s is not a parent of %s", parent, path->ptr); return GIT_ENOTFOUND; } if (*p == '/' && !*q) p++; else if (!*p && *q == '/') q++; else if (!*p && !*q) return git_buf_clear(path), 0; else { p = p_dirsep + 1; q = q_dirsep + 1; } plen -= (p - path->ptr); if (!*q) return git_buf_set(path, p, plen); for (; (q = strchr(q, '/')) && *(q + 1); q++) depth++; GITERR_CHECK_ALLOC_MULTIPLY(&newlen, depth, 3); GITERR_CHECK_ALLOC_ADD(&newlen, newlen, plen); GITERR_CHECK_ALLOC_ADD(&alloclen, newlen, 1); /* save the offset as we might realllocate the pointer */ offset = p - path->ptr; if (git_buf_try_grow(path, alloclen, 1, 0) < 0) return -1; p = path->ptr + offset; memmove(path->ptr + (depth * 3), p, plen + 1); for (i = 0; i < depth; i++) memcpy(path->ptr + (i * 3), "../", 3); path->size = newlen; return 0; }
int git_path_prettify(git_buf *path_out, const char *path, const char *base) { char buf[GIT_PATH_MAX]; assert(path && path_out); /* construct path if needed */ if (base != NULL && git_path_root(path) < 0) { if (git_buf_joinpath(path_out, base, path) < 0) return -1; path = path_out->ptr; } if (p_realpath(path, buf) == NULL) { /* giterr_set resets the errno when dealing with a GITERR_OS kind of error */ int error = (errno == ENOENT || errno == ENOTDIR) ? GIT_ENOTFOUND : -1; giterr_set(GITERR_OS, "Failed to resolve path '%s'", path); git_buf_clear(path_out); return error; } return git_buf_sets(path_out, buf); }
int git__percent_decode(git_buf *decoded_out, const char *input) { int len, hi, lo, i; assert(decoded_out && input); len = (int)strlen(input); git_buf_clear(decoded_out); for(i = 0; i < len; i++) { char c = input[i]; if (c != '%') goto append; if (i >= len - 2) goto append; hi = git__fromhex(input[i + 1]); lo = git__fromhex(input[i + 2]); if (hi < 0 || lo < 0) goto append; c = (char)(hi << 4 | lo); i += 2; append: if (git_buf_putc(decoded_out, c) < 0) return -1; } return 0; }
int git_reference_dwim(git_reference **out, git_repository *repo, const char *refname) { int error = 0, i; bool fallbackmode = true, foundvalid = false; git_reference *ref; git_buf refnamebuf = GIT_BUF_INIT, name = GIT_BUF_INIT; static const char* formatters[] = { "%s", GIT_REFS_DIR "%s", GIT_REFS_TAGS_DIR "%s", GIT_REFS_HEADS_DIR "%s", GIT_REFS_REMOTES_DIR "%s", GIT_REFS_REMOTES_DIR "%s/" GIT_HEAD_FILE, NULL }; if (*refname) git_buf_puts(&name, refname); else { git_buf_puts(&name, GIT_HEAD_FILE); fallbackmode = false; } for (i = 0; formatters[i] && (fallbackmode || i == 0); i++) { git_buf_clear(&refnamebuf); if ((error = git_buf_printf(&refnamebuf, formatters[i], git_buf_cstr(&name))) < 0) goto cleanup; if (!git_reference_is_valid_name(git_buf_cstr(&refnamebuf))) { error = GIT_EINVALIDSPEC; continue; } foundvalid = true; error = git_reference_lookup_resolved(&ref, repo, git_buf_cstr(&refnamebuf), -1); if (!error) { *out = ref; error = 0; goto cleanup; } if (error != GIT_ENOTFOUND) goto cleanup; } cleanup: if (error && !foundvalid) { /* never found a valid reference name */ giterr_set(GITERR_REFERENCE, "Could not use '%s' as valid reference name", git_buf_cstr(&name)); } git_buf_free(&name); git_buf_free(&refnamebuf); return error; }
int git_path_fromurl(git_buf *local_path_out, const char *file_url) { int offset = 0, len; assert(local_path_out && file_url); if (git__prefixcmp(file_url, "file://") != 0) return error_invalid_local_file_uri(file_url); offset += 7; len = (int)strlen(file_url); if (offset < len && file_url[offset] == '/') offset++; else if (offset < len && git__prefixcmp(file_url + offset, "localhost/") == 0) offset += 10; else return error_invalid_local_file_uri(file_url); if (offset >= len || file_url[offset] == '/') return error_invalid_local_file_uri(file_url); #ifndef _MSC_VER offset--; /* A *nix absolute path starts with a forward slash */ #endif git_buf_clear(local_path_out); return git__percent_decode(local_path_out, file_url + offset); }
static int rebase_state_type( git_rebase_type_t *type_out, char **path_out, git_repository *repo) { git_buf path = GIT_BUF_INIT; git_rebase_type_t type = GIT_REBASE_TYPE_NONE; if (git_buf_joinpath(&path, repo->path_repository, REBASE_APPLY_DIR) < 0) return -1; if (git_path_isdir(git_buf_cstr(&path))) { type = GIT_REBASE_TYPE_APPLY; goto done; } git_buf_clear(&path); if (git_buf_joinpath(&path, repo->path_repository, REBASE_MERGE_DIR) < 0) return -1; if (git_path_isdir(git_buf_cstr(&path))) { type = GIT_REBASE_TYPE_MERGE; goto done; } done: *type_out = type; if (type != GIT_REBASE_TYPE_NONE && path_out) *path_out = git_buf_detach(&path); git_buf_free(&path); return 0; }
static int git_futils_find_in_dirlist( git_buf *path, const char *name, git_futils_dir_t which, const char *label) { size_t len; const char *scan, *next = NULL; const git_buf *syspath; GITERR_CHECK_ERROR(git_futils_dirs_get(&syspath, which)); for (scan = git_buf_cstr(syspath); scan; scan = next) { for (next = strchr(scan, GIT_PATH_LIST_SEPARATOR); next && next > scan && next[-1] == '\\'; next = strchr(next + 1, GIT_PATH_LIST_SEPARATOR)) /* find unescaped separator or end of string */; len = next ? (size_t)(next++ - scan) : strlen(scan); if (!len) continue; GITERR_CHECK_ERROR(git_buf_set(path, scan, len)); GITERR_CHECK_ERROR(git_buf_joinpath(path, path->ptr, name)); if (git_path_exists(path->ptr)) return 0; } git_buf_clear(path); giterr_set(GITERR_OS, "The %s file '%s' doesn't exist", label, name); return GIT_ENOTFOUND; }
int git__percent_decode(git_buf *decoded_out, const char *input) { int len, hi, lo, i, error = GIT_SUCCESS; assert(decoded_out && input); len = strlen(input); git_buf_clear(decoded_out); for(i = 0; i < len; i++) { char c = input[i]; if (c != '%') goto append; if (i >= len - 2) goto append; hi = git__fromhex(input[i + 1]); lo = git__fromhex(input[i + 2]); if (hi < 0 || lo < 0) goto append; c = (char)(hi << 4 | lo); i += 2; append: error = git_buf_putc(decoded_out, c); if (error < GIT_SUCCESS) return git__rethrow(error, "Failed to percent decode '%s'.", input); } return error; }
static int refspec_transform( git_buf *out, const char *from, const char *to, const char *name) { const char *from_star, *to_star; size_t replacement_len, star_offset; git_buf_sanitize(out); git_buf_clear(out); /* * There are two parts to each side of a refspec, the bit * before the star and the bit after it. The star can be in * the middle of the pattern, so we need to look at each bit * individually. */ from_star = strchr(from, '*'); to_star = strchr(to, '*'); assert(from_star && to_star); /* star offset, both in 'from' and in 'name' */ star_offset = from_star - from; /* the first half is copied over */ git_buf_put(out, to, to_star - to); /* * Copy over the name, but exclude the trailing part in "from" starting * after the glob */ replacement_len = strlen(name + star_offset) - strlen(from_star + 1); git_buf_put(out, name + star_offset, replacement_len); return git_buf_puts(out, to_star + 1); }
void test_reset_mixed__reflog_is_correct(void) { git_buf buf = GIT_BUF_INIT; const char *exp_msg = "commit: Updating test data so we can test inter-hunk-context"; reflog_check(repo, "HEAD", 9, "*****@*****.**", exp_msg); reflog_check(repo, "refs/heads/master", 9, "*****@*****.**", exp_msg); /* Branch not moving, no reflog entry */ cl_git_pass(git_revparse_single(&target, repo, "HEAD^{commit}")); cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL)); reflog_check(repo, "HEAD", 9, "*****@*****.**", exp_msg); reflog_check(repo, "refs/heads/master", 9, "*****@*****.**", exp_msg); git_object_free(target); target = NULL; /* Moved branch, expect default message */ cl_git_pass(git_revparse_single(&target, repo, "HEAD~^{commit}")); git_buf_clear(&buf); cl_git_pass(git_buf_printf(&buf, "reset: moving to %s", git_oid_tostr_s(git_object_id(target)))); cl_git_pass(git_reset(repo, target, GIT_RESET_MIXED, NULL)); reflog_check(repo, "HEAD", 10, NULL, git_buf_cstr(&buf)); reflog_check(repo, "refs/heads/master", 10, NULL, git_buf_cstr(&buf)); git_buf_free(&buf); }
static void assert_email_match( const char *expected, const char *oidstr, git_diff_format_email_options *opts) { git_oid oid; git_commit *commit = NULL; git_diff *diff = NULL; git_buf buf = GIT_BUF_INIT; git_oid_fromstr(&oid, oidstr); cl_git_pass(git_commit_lookup(&commit, repo, &oid)); opts->id = git_commit_id(commit); opts->author = git_commit_author(commit); if (!opts->summary) opts->summary = git_commit_summary(commit); cl_git_pass(git_diff__commit(&diff, repo, commit, NULL)); cl_git_pass(git_diff_format_email(&buf, diff, opts)); cl_assert_equal_s(expected, git_buf_cstr(&buf)); git_buf_clear(&buf); cl_git_pass(git_diff_commit_as_email( &buf, repo, commit, 1, 1, opts->flags, NULL)); cl_assert_equal_s(expected, git_buf_cstr(&buf)); git_diff_free(diff); git_commit_free(commit); git_buf_free(&buf); }
int git_win32__find_system_dirs(git_buf *out, const wchar_t *subdir) { git_buf buf = GIT_BUF_INIT; /* directories where git.exe & git.cmd are found */ if (!win32_find_git_in_path(&buf, L"git.exe", subdir) && buf.size) git_buf_set(out, buf.ptr, buf.size); else git_buf_clear(out); if (!win32_find_git_in_path(&buf, L"git.cmd", subdir) && buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); /* directories where git is installed according to registry */ if (!win32_find_git_in_registry( &buf, HKEY_CURRENT_USER, REG_MSYSGIT_INSTALL_LOCAL, subdir) && buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); if (!win32_find_git_in_registry( &buf, HKEY_LOCAL_MACHINE, REG_MSYSGIT_INSTALL, subdir) && buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); git_buf_free(&buf); return (git_buf_oom(out) ? -1 : 0); }
static int prepare_worktree_commit_message( git_buf* msg, const char *user_message) { git_buf buf = GIT_BUF_INIT; int error; if ((error = git_buf_set(&buf, git_buf_cstr(msg), git_buf_len(msg))) < 0) return error; git_buf_clear(msg); if (!user_message) git_buf_printf(msg, "WIP on %s", git_buf_cstr(&buf)); else { const char *colon; if ((colon = strchr(git_buf_cstr(&buf), ':')) == NULL) goto cleanup; git_buf_puts(msg, "On "); git_buf_put(msg, git_buf_cstr(&buf), colon - buf.ptr); git_buf_printf(msg, ": %s\n", user_message); } error = (git_buf_oom(msg) || git_buf_oom(&buf)) ? -1 : 0; cleanup: git_buf_free(&buf); return error; }
static void hack_index(char *files[]) { char *filename; struct stat statbuf; git_buf path = GIT_BUF_INIT; git_index_entry *entry; size_t i; /* Update the index to suggest that checkout placed these files on * disk, keeping the object id but updating the cache, which will * emulate a Git implementation's different filter. */ for (i = 0, filename = files[i]; filename; filename = files[++i]) { git_buf_clear(&path); cl_assert(entry = (git_index_entry *) git_index_get_bypath(repo_index, filename, 0)); cl_git_pass(git_buf_printf(&path, "%s/%s", TEST_REPO_PATH, filename)); cl_git_pass(p_stat(path.ptr, &statbuf)); entry->ctime.seconds = (git_time_t)statbuf.st_ctime; entry->ctime.nanoseconds = 0; entry->mtime.seconds = (git_time_t)statbuf.st_mtime; entry->mtime.nanoseconds = 0; entry->dev = statbuf.st_dev; entry->ino = statbuf.st_ino; entry->uid = statbuf.st_uid; entry->gid = statbuf.st_gid; entry->file_size = statbuf.st_size; } git_buf_free(&path); }
static int rebase_setupfiles_merge(git_rebase *rebase) { git_buf commit_filename = GIT_BUF_INIT; char id_str[GIT_OID_HEXSZ]; git_rebase_operation *operation; size_t i; int error = 0; if ((error = rebase_setupfile(rebase, END_FILE, -1, "%" PRIuZ "\n", git_array_size(rebase->operations))) < 0 || (error = rebase_setupfile(rebase, ONTO_NAME_FILE, -1, "%s\n", rebase->onto_name)) < 0) goto done; for (i = 0; i < git_array_size(rebase->operations); i++) { operation = git_array_get(rebase->operations, i); git_buf_clear(&commit_filename); git_buf_printf(&commit_filename, CMT_FILE_FMT, i+1); git_oid_fmt(id_str, &operation->id); if ((error = rebase_setupfile(rebase, commit_filename.ptr, -1, "%.*s\n", GIT_OID_HEXSZ, id_str)) < 0) goto done; } done: git_buf_free(&commit_filename); return error; }
int git_commit_header_field(git_buf *out, const git_commit *commit, const char *field) { const char *eol, *buf = commit->raw_header; git_buf_clear(out); while ((eol = strchr(buf, '\n'))) { /* We can skip continuations here */ if (buf[0] == ' ') { buf = eol + 1; continue; } /* Skip until we find the field we're after */ if (git__prefixcmp(buf, field)) { buf = eol + 1; continue; } buf += strlen(field); /* Check that we're not matching a prefix but the field itself */ if (buf[0] != ' ') { buf = eol + 1; continue; } buf++; /* skip the SP */ git_buf_put(out, buf, eol - buf); if (git_buf_oom(out)) goto oom; /* If the next line starts with SP, it's multi-line, we must continue */ while (eol[1] == ' ') { git_buf_putc(out, '\n'); buf = eol + 2; eol = strchr(buf, '\n'); if (!eol) goto malformed; git_buf_put(out, buf, eol - buf); } if (git_buf_oom(out)) goto oom; return 0; } giterr_set(GITERR_OBJECT, "no such field '%s'", field); return GIT_ENOTFOUND; malformed: giterr_set(GITERR_OBJECT, "malformed header"); return -1; oom: giterr_set_oom(); return -1; }
static bool try_create_file_with_nsec_timestamp(const char *path) { struct stat st; int try; /* retry a few times to avoid nanos *actually* equal 0 race condition */ for (try = 0; try < 3; try++) { cl_git_mkfile(path, "This is hopefully a file with nanoseconds!"); cl_must_pass(p_stat(path, &st)); if (st.st_ctime_nsec && st.st_mtime_nsec) return true; } return false; } /* try to determine if the underlying filesystem supports a resolution * higher than a single second. (i'm looking at you, hfs+) */ static bool should_expect_nsecs(void) { git_buf nsec_path = GIT_BUF_INIT; bool expect; git_buf_joinpath(&nsec_path, clar_sandbox_path(), "nsec_test"); expect = try_create_file_with_nsec_timestamp(nsec_path.ptr); p_unlink(nsec_path.ptr); git_buf_clear(&nsec_path); return expect; } static bool has_nsecs(void) { const git_index_entry *entry; size_t i; bool has_nsecs = false; for (i = 0; i < git_index_entrycount(repo_index); i++) { entry = git_index_get_byindex(repo_index, i); if (entry->ctime.nanoseconds || entry->mtime.nanoseconds) { has_nsecs = true; break; } } return has_nsecs; } void test_index_nsec__has_nanos(void) { cl_assert_equal_b(true, has_nsecs()); }
static int file_url(git_buf *buf, const char *host, const char *path) { if (path[0] == '/') path++; git_buf_clear(buf); return git_buf_printf(buf, "file://%s/%s", host, path); }