Commit 0a7c00be by lhchavez

Merge remote-tracking branch 'origin/main' into main

parents a7541676 2b28ee77
......@@ -6,7 +6,7 @@ on:
- cron: '21 3 * * 1'
env:
docker-registry: docker.pkg.github.com
docker-registry: ghcr.io
jobs:
analyze:
......
......@@ -10,7 +10,7 @@ on:
workflow_dispatch:
env:
docker-registry: docker.pkg.github.com
docker-registry: ghcr.io
docker-config-path: source/ci/docker
jobs:
......@@ -69,7 +69,7 @@ jobs:
if [ "${{ matrix.container.base }}" != "" ]; then
BASE_ARG="--build-arg BASE=${{ matrix.container.base }}"
fi
docker build -t ${{ env.docker-registry-container-sha }} ${BASE_ARG} -f ${{ env.dockerfile }} .
docker build -t ${{ env.docker-registry-container-sha }} --build-arg UID=$(id -u) --build-arg GID=$(id -g) ${BASE_ARG} -f ${{ env.dockerfile }} .
docker tag ${{ env.docker-registry-container-sha }} ${{ env.docker-registry-container-latest }}
docker push ${{ env.docker-registry-container-sha }}
docker push ${{ env.docker-registry-container-latest }}
......@@ -85,6 +85,7 @@ jobs:
matrix:
platform:
- name: "Linux (Xenial, GCC, OpenSSL)"
id: xenial-gcc-openssl
container:
name: xenial
env:
......@@ -93,6 +94,7 @@ jobs:
CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON -DDEBUG_STRICT_ALLOC=ON -DDEBUG_STRICT_OPEN=ON
os: ubuntu-latest
- name: Linux (Xenial, GCC, mbedTLS)
id: xenial-gcc-mbedtls
container:
name: xenial
env:
......@@ -101,6 +103,7 @@ jobs:
CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
os: ubuntu-latest
- name: "Linux (Xenial, Clang, OpenSSL)"
id: xenial-clang-openssl
container:
name: xenial
env:
......@@ -109,6 +112,7 @@ jobs:
CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON -DUSE_SSH=ON
os: ubuntu-latest
- name: "Linux (Xenial, Clang, mbedTLS)"
id: xenial-clang-mbedtls
container:
name: xenial
env:
......@@ -117,6 +121,7 @@ jobs:
CMAKE_GENERATOR: Ninja
os: ubuntu-latest
- name: "Linux (MemorySanitizer)"
id: memorysanitizer
container:
name: focal
env:
......@@ -130,6 +135,7 @@ jobs:
UBSAN_OPTIONS: print_stacktrace=1
os: ubuntu-latest
- name: "Linux (UndefinedBehaviorSanitizer)"
id: ubsanitizer
container:
name: focal
env:
......@@ -143,6 +149,7 @@ jobs:
UBSAN_OPTIONS: print_stacktrace=1
os: ubuntu-latest
- name: "Linux (ThreadSanitizer)"
id: threadsanitizer
container:
name: focal
env:
......@@ -157,6 +164,7 @@ jobs:
TSAN_OPTIONS: suppressions=/home/libgit2/source/script/thread-sanitizer.supp second_deadlock_stack=1
os: ubuntu-latest
- name: "macOS"
id: macos
os: macos-10.15
env:
CC: clang
......@@ -166,6 +174,7 @@ jobs:
SKIP_NEGOTIATE_TESTS: true
setup-script: osx
- name: "Windows (amd64, Visual Studio)"
id: windows-amd64-vs
os: windows-2019
env:
ARCH: amd64
......@@ -174,6 +183,7 @@ jobs:
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, Visual Studio)"
id: windows-x86-vs
os: windows-2019
env:
ARCH: x86
......@@ -182,6 +192,7 @@ jobs:
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (amd64, mingw)"
id: windows-amd64-mingw
os: windows-2019
setup-script: mingw
env:
......@@ -193,6 +204,7 @@ jobs:
SKIP_SSH_TESTS: true
SKIP_NEGOTIATE_TESTS: true
- name: "Windows (x86, mingw)"
id: windows-x86-mingw
os: windows-2019
setup-script: mingw
env:
......@@ -237,10 +249,12 @@ jobs:
export GITTEST_NEGOTIATE_PASSWORD="${{ secrets.GITTEST_NEGOTIATE_PASSWORD }}"
if [ -n "${{ matrix.platform.container.name }}" ]; then
mkdir build
docker run \
--rm \
--user libgit2:libgit2 \
--user "$(id -u):$(id -g)" \
-v "$(pwd)/source:/home/libgit2/source" \
-v "$(pwd)/build:/home/libgit2/build" \
-w /home/libgit2 \
-e ASAN_SYMBOLIZER_PATH \
-e CC \
......@@ -255,13 +269,33 @@ jobs:
-e TSAN_OPTIONS \
-e UBSAN_OPTIONS \
${{ env.docker-registry-container-sha }} \
/bin/bash -c "mkdir build && cd build && ../source/ci/build.sh && ../source/ci/test.sh"
/bin/bash -c "cd build && ../source/ci/build.sh && ../source/ci/test.sh"
else
mkdir build && cd build
mkdir build
cd build
../source/ci/build.sh
../source/ci/test.sh
fi
shell: bash
- name: Upload test results
uses: actions/upload-artifact@v3
if: success() || failure()
with:
name: test-results-${{ matrix.platform.id }}
path: build/results_*.xml
test_results:
name: Test results
needs: [ build ]
runs-on: ubuntu-latest
steps:
- name: Download test results
uses: actions/download-artifact@v3
- name: Generate test summary
uses: test-summary/action@v1
with:
paths: 'test-results-*/*.xml'
# Generate documentation using docurium. We'll upload the documentation
# as a build artifact so that it can be reviewed as part of a pull
......@@ -271,6 +305,7 @@ jobs:
documentation:
name: Generate documentation
needs: [ containers ]
if: success() || failure()
runs-on: ubuntu-latest
steps:
- name: Check out repository
......
......@@ -7,7 +7,7 @@ on:
- cron: '15 1 * * *'
env:
docker-registry: docker.pkg.github.com
docker-registry: ghcr.io
docker-config-path: source/ci/docker
jobs:
......
......@@ -392,6 +392,8 @@ Here are the bindings to libgit2 that are currently available:
* parrot-libgit2 <https://github.com/letolabs/parrot-libgit2>
* Perl
* Git-Raw <https://github.com/jacquesg/p5-Git-Raw>
* Pharo Smalltalk
* libgit2-pharo-bindings <https://github.com/pharo-vcs/libgit2-pharo-bindings>
* PHP
* php-git <https://github.com/libgit2/php-git>
* Python
......@@ -405,6 +407,8 @@ Here are the bindings to libgit2 that are currently available:
* git2-rs <https://github.com/rust-lang/git2-rs>
* Swift
* SwiftGit2 <https://github.com/SwiftGit2/SwiftGit2>
* Tcl
* lg2 <https://github.com/apnadkarni/tcl-libgit2>
* Vala
* libgit2.vapi <https://github.com/apmasell/vapis/blob/master/libgit2.vapi>
......
......@@ -38,7 +38,12 @@ RUN cd /tmp && \
rm -rf mbedtls-2.16.2
FROM mbedtls AS adduser
RUN useradd --shell /bin/bash libgit2 --create-home
ARG UID=""
ARG GID=""
RUN if [ "${UID}" != "" ]; then USER_ARG="--uid ${UID}"; fi && \
if [ "${GID}" != "" ]; then GROUP_ARG="--gid ${GID}"; fi && \
groupadd ${GROUP_ARG} libgit2 && \
useradd ${USER_ARG} --gid libgit2 --shell /bin/bash --create-home libgit2
FROM adduser AS configure
RUN mkdir /var/run/sshd
......@@ -48,7 +48,12 @@ RUN cd /tmp && \
rm -rf cmake-3.21.1
FROM cmake AS adduser
RUN useradd --shell /bin/bash libgit2 --create-home
ARG UID=""
ARG GID=""
RUN if [ "${UID}" != "" ]; then USER_ARG="--uid ${UID}"; fi && \
if [ "${GID}" != "" ]; then GROUP_ARG="--gid ${GID}"; fi && \
groupadd ${GROUP_ARG} libgit2 && \
useradd ${USER_ARG} --gid libgit2 --shell /bin/bash --create-home libgit2
FROM adduser AS configure
ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig
......
ARG BASE=centos:8
FROM ${BASE} AS yum
FROM ${BASE} AS stream
RUN dnf -y --disablerepo '*' --enablerepo=extras swap centos-linux-repos centos-stream-repos && \
dnf -y distro-sync
FROM stream AS yum
RUN yum install -y \
which \
bzip2 \
......@@ -40,7 +44,12 @@ RUN cd /tmp && \
rm -rf valgrind-3.15.0
FROM valgrind AS adduser
RUN useradd --shell /bin/bash libgit2 --create-home
ARG UID=""
ARG GID=""
RUN if [ "${UID}" != "" ]; then USER_ARG="--uid ${UID}"; fi && \
if [ "${GID}" != "" ]; then GROUP_ARG="--gid ${GID}"; fi && \
groupadd ${GROUP_ARG} libgit2 && \
useradd ${USER_ARG} --gid libgit2 --shell /bin/bash --create-home libgit2
FROM adduser AS configure
ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig
......
......@@ -73,7 +73,13 @@ RUN cd /tmp && \
rm -rf valgrind-3.15.0
FROM valgrind AS adduser
RUN useradd --shell /bin/bash libgit2 --create-home
ARG UID=""
ARG GID=""
RUN if [ "${UID}" != "" ]; then USER_ARG="--uid ${UID}"; fi && \
if [ "${GID}" != "" ]; then GROUP_ARG="--gid ${GID}"; fi && \
groupadd ${GROUP_ARG} libgit2 && \
useradd ${USER_ARG} --gid libgit2 --shell /bin/bash --create-home libgit2
FROM adduser AS configure
RUN mkdir /var/run/sshd
......@@ -60,7 +60,13 @@ RUN cd /tmp && \
rm -rf valgrind-3.15.0
FROM valgrind AS adduser
RUN useradd --shell /bin/bash libgit2 --create-home
ARG UID=""
ARG GID=""
RUN if [ "${UID}" != "" ]; then USER_ARG="--uid ${UID}"; fi && \
if [ "${GID}" != "" ]; then GROUP_ARG="--gid ${GID}"; fi && \
groupadd ${GROUP_ARG} libgit2 && \
useradd ${USER_ARG} --gid libgit2 --shell /bin/bash --create-home libgit2
FROM adduser AS configure
RUN mkdir /var/run/sshd
......@@ -37,9 +37,13 @@ DOCKER_REGISTRY_CONTAINER_SHA="${DOCKER_REGISTRY_CONTAINER}:${DOCKER_SHA}"
echo "docker-registry-container-sha=${DOCKER_REGISTRY_CONTAINER_SHA}" >> $GITHUB_ENV
echo "docker-registry-container-latest=${DOCKER_REGISTRY_CONTAINER}:latest" >> $GITHUB_ENV
echo "::: logging in to ${DOCKER_REGISTRY} as ${GITHUB_ACTOR}"
exists="true"
docker login https://${DOCKER_REGISTRY} -u ${GITHUB_ACTOR} -p ${GITHUB_TOKEN} || exists="false"
echo "::: pulling ${DOCKER_REGISTRY_CONTAINER_SHA}"
if [ "${exists}" != "false" ]; then
docker pull ${DOCKER_REGISTRY_CONTAINER_SHA} || exists="false"
fi
......
......@@ -94,7 +94,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
fprintf(stderr, "Failed to compute the SHA1 hash\n");
abort();
}
if (git_indexer_append(indexer, &oid, sizeof(oid), &stats) < 0) {
if (git_indexer_append(indexer, &oid.id, GIT_OID_RAWSZ, &stats) < 0) {
goto cleanup;
}
}
......
......@@ -129,8 +129,8 @@ GIT_EXTERN(void) git_branch_iterator_free(git_branch_iterator *iter);
* See `git_tag_create()` for rules about valid names.
*
* Note that if the move succeeds, the old reference object will not
+ be valid anymore, and should be freed immediately by the user using
+ `git_reference_free()`.
* be valid anymore, and should be freed immediately by the user using
* `git_reference_free()`.
*
* @param out New reference object for the updated name.
*
......
......@@ -122,7 +122,7 @@ typedef struct {
* global configuration file.
*
* This method will not guess the path to the xdg compatible
* config file (.config/git/config).
* config file (`.config/git/config`).
*
* @param out Pointer to a user-allocated git_buf in which to store the path
* @return 0 if a global configuration file has been found. Its path will be stored in `out`.
......@@ -149,8 +149,8 @@ GIT_EXTERN(int) git_config_find_xdg(git_buf *out);
/**
* Locate the path to the system configuration file
*
* If /etc/gitconfig doesn't exist, it will look for
* %PROGRAMFILES%\Git\etc\gitconfig.
* If `/etc/gitconfig` doesn't exist, it will look for
* `%PROGRAMFILES%\Git\etc\gitconfig`.
*
* @param out Pointer to a user-allocated git_buf in which to store the path
* @return 0 if a system configuration file has been
......@@ -161,7 +161,7 @@ GIT_EXTERN(int) git_config_find_system(git_buf *out);
/**
* Locate the path to the configuration file in ProgramData
*
* Look for the file in %PROGRAMDATA%\Git\config used by portable git.
* Look for the file in `%PROGRAMDATA%\Git\config` used by portable git.
*
* @param out Pointer to a user-allocated git_buf in which to store the path
* @return 0 if a ProgramData configuration file has been
......
......@@ -603,7 +603,7 @@ GIT_EXTERN(int) git_merge_commits(
* completes, resolve any conflicts and prepare a commit.
*
* For compatibility with git, the repository is put into a merging
* state. Once the commit is done (or if the uses wishes to abort),
* state. Once the commit is done (or if the user wishes to abort),
* you should clear this state by calling
* `git_repository_state_cleanup()`.
*
......
......@@ -15,5 +15,6 @@
#include "error.h"
#include "opt.h"
#include "opt_usage.h"
#include "sighandler.h"
#endif /* CLI_cli_h__ */
......@@ -26,6 +26,7 @@ extern const cli_cmd_spec *cli_cmd_spec_byname(const char *name);
/* Commands */
extern int cmd_cat_file(int argc, char **argv);
extern int cmd_clone(int argc, char **argv);
extern int cmd_hash_object(int argc, char **argv);
extern int cmd_help(int argc, char **argv);
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include <stdio.h>
#include <git2.h>
#include "cli.h"
#include "cmd.h"
#include "error.h"
#include "sighandler.h"
#include "progress.h"
#include "fs_path.h"
#include "futils.h"
#define COMMAND_NAME "clone"
static char *branch, *remote_path, *local_path;
static int show_help, quiet, checkout = 1, bare;
static bool local_path_exists;
static cli_progress progress = CLI_PROGRESS_INIT;
static const cli_opt_spec opts[] = {
{ CLI_OPT_TYPE_SWITCH, "help", 0, &show_help, 1,
CLI_OPT_USAGE_HIDDEN | CLI_OPT_USAGE_STOP_PARSING, NULL,
"display help about the " COMMAND_NAME " command" },
{ CLI_OPT_TYPE_SWITCH, "quiet", 'q', &quiet, 1,
CLI_OPT_USAGE_DEFAULT, NULL, "display the type of the object" },
{ CLI_OPT_TYPE_SWITCH, "no-checkout", 'n', &checkout, 0,
CLI_OPT_USAGE_DEFAULT, NULL, "don't checkout HEAD" },
{ CLI_OPT_TYPE_SWITCH, "bare", 0, &bare, 1,
CLI_OPT_USAGE_DEFAULT, NULL, "don't create a working directory" },
{ CLI_OPT_TYPE_VALUE, "branch", 'b', &branch, 0,
CLI_OPT_USAGE_DEFAULT, "name", "branch to check out" },
{ CLI_OPT_TYPE_LITERAL },
{ CLI_OPT_TYPE_ARG, "repository", 0, &remote_path, 0,
CLI_OPT_USAGE_REQUIRED, "repository", "repository path" },
{ CLI_OPT_TYPE_ARG, "directory", 0, &local_path, 0,
CLI_OPT_USAGE_DEFAULT, "directory", "directory to clone into" },
{ 0 }
};
static void print_help(void)
{
cli_opt_usage_fprint(stdout, PROGRAM_NAME, COMMAND_NAME, opts);
printf("\n");
printf("Clone a repository into a new directory.\n");
printf("\n");
printf("Options:\n");
cli_opt_help_fprint(stdout, opts);
}
static char *compute_local_path(const char *orig_path)
{
const char *slash;
char *local_path;
if ((slash = strrchr(orig_path, '/')) == NULL &&
(slash = strrchr(orig_path, '\\')) == NULL)
local_path = git__strdup(orig_path);
else
local_path = git__strdup(slash + 1);
return local_path;
}
static bool validate_local_path(const char *path)
{
if (!git_fs_path_exists(path))
return false;
if (!git_fs_path_isdir(path) || !git_fs_path_is_empty_dir(path)) {
fprintf(stderr, "fatal: destination path '%s' already exists and is not an empty directory.\n",
path);
exit(128);
}
return true;
}
static void cleanup(void)
{
int rmdir_flags = GIT_RMDIR_REMOVE_FILES;
cli_progress_abort(&progress);
if (local_path_exists)
rmdir_flags |= GIT_RMDIR_SKIP_ROOT;
if (!git_fs_path_isdir(local_path))
return;
git_futils_rmdir_r(local_path, NULL, rmdir_flags);
}
static void interrupt_cleanup(void)
{
cleanup();
exit(130);
}
int cmd_clone(int argc, char **argv)
{
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
git_repository *repo = NULL;
cli_opt invalid_opt;
char *computed_path = NULL;
int ret = 0;
if (cli_opt_parse(&invalid_opt, opts, argv + 1, argc - 1, CLI_OPT_PARSE_GNU))
return cli_opt_usage_error(COMMAND_NAME, opts, &invalid_opt);
if (show_help) {
print_help();
return 0;
}
if (!remote_path) {
ret = cli_error_usage("you must specify a repository to clone");
goto done;
}
if (bare)
clone_opts.bare = 1;
if (branch)
clone_opts.checkout_branch = branch;
if (!checkout)
clone_opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE;
if (!local_path)
local_path = computed_path = compute_local_path(remote_path);
local_path_exists = validate_local_path(local_path);
cli_sighandler_set_interrupt(interrupt_cleanup);
if (!local_path_exists &&
git_futils_mkdir(local_path, 0777, 0) < 0) {
ret = cli_error_git();
goto done;
}
if (!quiet) {
clone_opts.fetch_opts.callbacks.sideband_progress = cli_progress_fetch_sideband;
clone_opts.fetch_opts.callbacks.transfer_progress = cli_progress_fetch_transfer;
clone_opts.fetch_opts.callbacks.payload = &progress;
clone_opts.checkout_opts.progress_cb = cli_progress_checkout;
clone_opts.checkout_opts.progress_payload = &progress;
printf("Cloning into '%s'...\n", local_path);
}
if (git_clone(&repo, remote_path, local_path, &clone_opts) < 0) {
cleanup();
ret = cli_error_git();
goto done;
}
cli_progress_finish(&progress);
done:
cli_progress_dispose(&progress);
git__free(computed_path);
git_repository_free(repo);
return ret;
}
......@@ -29,6 +29,7 @@ const cli_opt_spec cli_common_opts[] = {
const cli_cmd_spec cli_cmds[] = {
{ "cat-file", cmd_cat_file, "Display an object in the repository" },
{ "clone", cmd_clone, "Clone a repository into a new directory" },
{ "hash-object", cmd_hash_object, "Hash a raw object and product its object ID" },
{ "help", cmd_help, "Display help information" },
{ NULL }
......
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include "progress.h"
#include "error.h"
/*
* Show updates to the percentage and number of objects received
* separately from the throughput to give an accurate progress while
* avoiding too much noise on the screen.
*/
#define PROGRESS_UPDATE_TIME 0.10
#define THROUGHPUT_UPDATE_TIME 1.00
#define is_nl(c) ((c) == '\r' || (c) == '\n')
#define return_os_error(msg) do { \
git_error_set(GIT_ERROR_OS, "%s", msg); return -1; } while(0)
GIT_INLINE(size_t) no_nl_len(const char *str, size_t len)
{
size_t i = 0;
while (i < len && !is_nl(str[i]))
i++;
return i;
}
GIT_INLINE(size_t) nl_len(bool *has_nl, const char *str, size_t len)
{
size_t i = no_nl_len(str, len);
*has_nl = false;
while (i < len && is_nl(str[i])) {
*has_nl = true;
i++;
}
return i;
}
static int progress_write(cli_progress *progress, bool force, git_str *line)
{
bool has_nl;
size_t no_nl = no_nl_len(line->ptr, line->size);
size_t nl = nl_len(&has_nl, line->ptr + no_nl, line->size - no_nl);
double now = git__timer();
size_t i;
/* Avoid spamming the console with progress updates */
if (!force && line->ptr[line->size - 1] != '\n' && progress->last_update) {
if (now - progress->last_update < PROGRESS_UPDATE_TIME) {
git_str_clear(&progress->deferred);
git_str_put(&progress->deferred, line->ptr, line->size);
return git_str_oom(&progress->deferred) ? -1 : 0;
}
}
/*
* If there's something on this line already (eg, a progress line
* with only a trailing `\r` that we'll print over) then we need
* to really print over it in case we're writing a shorter line.
*/
if (printf("%.*s", (int)no_nl, line->ptr) < 0)
return_os_error("could not print status");
if (progress->onscreen.size) {
for (i = no_nl; i < progress->onscreen.size; i++) {
if (printf(" ") < 0)
return_os_error("could not print status");
}
}
if (printf("%.*s", (int)nl, line->ptr + no_nl) < 0 ||
fflush(stdout) != 0)
return_os_error("could not print status");
git_str_clear(&progress->onscreen);
if (line->ptr[line->size - 1] == '\n') {
progress->last_update = 0;
} else {
git_str_put(&progress->onscreen, line->ptr, line->size);
progress->last_update = now;
}
git_str_clear(&progress->deferred);
return git_str_oom(&progress->onscreen) ? -1 : 0;
}
static int progress_printf(cli_progress *progress, bool force, const char *fmt, ...)
GIT_FORMAT_PRINTF(3, 4);
int progress_printf(cli_progress *progress, bool force, const char *fmt, ...)
{
git_str buf = GIT_BUF_INIT;
va_list ap;
int error;
va_start(ap, fmt);
error = git_str_vprintf(&buf, fmt, ap);
va_end(ap);
if (error < 0)
return error;
error = progress_write(progress, force, &buf);
git_str_dispose(&buf);
return error;
}
static int progress_complete(cli_progress *progress)
{
if (progress->deferred.size)
progress_write(progress, true, &progress->deferred);
if (progress->onscreen.size)
if (printf("\n") < 0)
return_os_error("could not print status");
git_str_clear(&progress->deferred);
git_str_clear(&progress->onscreen);
progress->last_update = 0;
progress->action_start = 0;
progress->action_finish = 0;
return 0;
}
GIT_INLINE(int) percent(size_t completed, size_t total)
{
if (total == 0)
return (completed == 0) ? 100 : 0;
return (int)(((double)completed / (double)total) * 100);
}
int cli_progress_fetch_sideband(const char *str, int len, void *payload)
{
cli_progress *progress = (cli_progress *)payload;
size_t remain;
if (len <= 0)
return 0;
/* Accumulate the sideband data, then print it line-at-a-time. */
if (git_str_put(&progress->sideband, str, len) < 0)
return -1;
str = progress->sideband.ptr;
remain = progress->sideband.size;
while (remain) {
bool has_nl;
size_t line_len = nl_len(&has_nl, str, remain);
if (!has_nl)
break;
if (line_len < INT_MAX) {
int error = progress_printf(progress, true,
"remote: %.*s", (int)line_len, str);
if (error < 0)
return error;
}
str += line_len;
remain -= line_len;
}
git_str_consume_bytes(&progress->sideband, (progress->sideband.size - remain));
return 0;
}
static int fetch_receiving(
cli_progress *progress,
const git_indexer_progress *stats)
{
char *recv_units[] = { "B", "KiB", "MiB", "GiB", "TiB", NULL };
char *rate_units[] = { "B/s", "KiB/s", "MiB/s", "GiB/s", "TiB/s", NULL };
double now, recv_len, rate, elapsed;
size_t recv_unit_idx = 0, rate_unit_idx = 0;
bool done = (stats->received_objects == stats->total_objects);
if (!progress->action_start)
progress->action_start = git__timer();
if (done && progress->action_finish)
now = progress->action_finish;
else if (done)
progress->action_finish = now = git__timer();
else
now = git__timer();
if (progress->throughput_update &&
now - progress->throughput_update < THROUGHPUT_UPDATE_TIME) {
elapsed = progress->throughput_update -
progress->action_start;
recv_len = progress->throughput_bytes;
} else {
elapsed = now - progress->action_start;
recv_len = (double)stats->received_bytes;
progress->throughput_update = now;
progress->throughput_bytes = recv_len;
}
rate = elapsed ? recv_len / elapsed : 0;
while (recv_len > 1024 && recv_units[recv_unit_idx+1]) {
recv_len /= 1024;
recv_unit_idx++;
}
while (rate > 1024 && rate_units[rate_unit_idx+1]) {
rate /= 1024;
rate_unit_idx++;
}
return progress_printf(progress, false,
"Receiving objects: %3d%% (%d/%d), %.2f %s | %.2f %s%s\r",
percent(stats->received_objects, stats->total_objects),
stats->received_objects,
stats->total_objects,
recv_len, recv_units[recv_unit_idx],
rate, rate_units[rate_unit_idx],
done ? ", done." : "");
}
static int fetch_resolving(
cli_progress *progress,
const git_indexer_progress *stats)
{
bool done = (stats->indexed_deltas == stats->total_deltas);
return progress_printf(progress, false,
"Resolving deltas: %3d%% (%d/%d)%s\r",
percent(stats->indexed_deltas, stats->total_deltas),
stats->indexed_deltas, stats->total_deltas,
done ? ", done." : "");
}
int cli_progress_fetch_transfer(const git_indexer_progress *stats, void *payload)
{
cli_progress *progress = (cli_progress *)payload;
int error = 0;
switch (progress->action) {
case CLI_PROGRESS_NONE:
progress->action = CLI_PROGRESS_RECEIVING;
/* fall through */
case CLI_PROGRESS_RECEIVING:
if ((error = fetch_receiving(progress, stats)) < 0)
break;
/*
* Upgrade from receiving to resolving; do this after the
* final call to cli_progress_fetch_receiving (above) to
* ensure that we've printed a final "done" string after
* any sideband data.
*/
if (!stats->indexed_deltas)
break;
progress_complete(progress);
progress->action = CLI_PROGRESS_RESOLVING;
/* fall through */
case CLI_PROGRESS_RESOLVING:
error = fetch_resolving(progress, stats);
break;
default:
/* should not be reached */
GIT_ASSERT(!"unexpected progress state");
}
return error;
}
void cli_progress_checkout(
const char *path,
size_t completed_steps,
size_t total_steps,
void *payload)
{
cli_progress *progress = (cli_progress *)payload;
bool done = (completed_steps == total_steps);
GIT_UNUSED(path);
if (progress->action != CLI_PROGRESS_CHECKING_OUT) {
progress_complete(progress);
progress->action = CLI_PROGRESS_CHECKING_OUT;
}
progress_printf(progress, false,
"Checking out files: %3d%% (%" PRIuZ "/%" PRIuZ ")%s\r",
percent(completed_steps, total_steps),
completed_steps, total_steps,
done ? ", done." : "");
}
int cli_progress_abort(cli_progress *progress)
{
if (progress->onscreen.size > 0 && printf("\n") < 0)
return_os_error("could not print status");
return 0;
}
int cli_progress_finish(cli_progress *progress)
{
int error = progress->action ? progress_complete(progress) : 0;
progress->action = 0;
return error;
}
void cli_progress_dispose(cli_progress *progress)
{
if (progress == NULL)
return;
git_str_dispose(&progress->sideband);
git_str_dispose(&progress->onscreen);
git_str_dispose(&progress->deferred);
memset(progress, 0, sizeof(cli_progress));
}
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef CLI_progress_h__
#define CLI_progress_h__
#include <git2.h>
#include "str.h"
/*
* A general purpose set of progress printing functions. An individual
* `cli_progress` object is capable of displaying progress for a single
* function, even if that function displays multiple pieces of progress
* (like `git_clone`). `cli_progress_finish` should be called after
* any function invocation to re-set state.
*/
typedef enum {
CLI_PROGRESS_NONE,
CLI_PROGRESS_RECEIVING,
CLI_PROGRESS_RESOLVING,
CLI_PROGRESS_CHECKING_OUT
} cli_progress_t;
typedef struct {
cli_progress_t action;
/* Actions may time themselves (eg fetch) but are not required to */
double action_start;
double action_finish;
/* Last console update, avoid too frequent updates. */
double last_update;
/* Accumulators for partial output and deferred updates. */
git_str sideband;
git_str onscreen;
git_str deferred;
/* Last update about throughput */
double throughput_update;
double throughput_bytes;
} cli_progress;
#define CLI_PROGRESS_INIT { 0 }
/**
* Prints sideband data from fetch to the console. Suitable for a
* `sideband_progress` callback for `git_fetch_options`.
*
* @param str The sideband string
* @param len The length of the sideband string
* @param payload A pointer to the cli_progress
* @return 0 on success, -1 on failure
*/
extern int cli_progress_fetch_sideband(
const char *str,
int len,
void *payload);
/**
* Prints fetch transfer statistics to the console. Suitable for a
* `transfer_progress` callback for `git_fetch_options`.
*
* @param stats The indexer stats
* @param payload A pointer to the cli_progress
* @return 0 on success, -1 on failure
*/
extern int cli_progress_fetch_transfer(
const git_indexer_progress *stats,
void *payload);
/**
* Prints checkout progress to the console. Suitable for a
* `progress_cb` callback for `git_checkout_options`.
*
* @param path The path being written
* @param completed_steps The completed checkout steps
* @param total_steps The total number of checkout steps
* @param payload A pointer to the cli_progress
*/
extern void cli_progress_checkout(
const char *path,
size_t completed_steps,
size_t total_steps,
void *payload);
/**
* Stop displaying progress quickly; suitable for stopping an application
* quickly. Does not display any lines that were buffered, just gets the
* console back to a sensible place.
*
* @param progress The progress information
* @return 0 on success, -1 on failure
*/
extern int cli_progress_abort(cli_progress *progress);
/**
* Finishes displaying progress; flushes any buffered output.
*
* @param progress The progress information
* @return 0 on success, -1 on failure
*/
extern int cli_progress_finish(cli_progress *progress);
/**
* Disposes the progress information.
*
* @param progress The progress information
*/
extern void cli_progress_dispose(cli_progress *progress);
#endif /* CLI_progress_h__ */
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef CLI_sighandler_h__
#define CLI_sighandler_h__
/**
* Sets up a signal handler that will run when the process is interrupted
* (via SIGINT on POSIX or Control-C or Control-Break on Windows).
*
* @param handler The function to run on interrupt
* @return 0 on success, -1 on failure
*/
int cli_sighandler_set_interrupt(void (*handler)(void));
#endif /* CLI_sighandler_h__ */
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include <stdint.h>
#include <signal.h>
#include "git2_util.h"
#include "cli.h"
static void (*interrupt_handler)(void) = NULL;
static void interrupt_proxy(int signal)
{
GIT_UNUSED(signal);
interrupt_handler();
}
int cli_sighandler_set_interrupt(void (*handler)(void))
{
void (*result)(int);
if ((interrupt_handler = handler) != NULL)
result = signal(SIGINT, interrupt_proxy);
else
result = signal(SIGINT, SIG_DFL);
if (result == SIG_ERR) {
git_error_set(GIT_ERROR_OS, "could not set signal handler");
return -1;
}
return 0;
}
/*
* Copyright (C) the libgit2 contributors. All rights reserved.
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#include "git2_util.h"
#include <windows.h>
#include "cli.h"
static void (*interrupt_handler)(void) = NULL;
static BOOL WINAPI interrupt_proxy(DWORD signal)
{
GIT_UNUSED(signal);
interrupt_handler();
return TRUE;
}
int cli_sighandler_set_interrupt(void (*handler)(void))
{
BOOL result;
if ((interrupt_handler = handler) != NULL)
result = SetConsoleCtrlHandler(interrupt_proxy, FALSE);
else
result = SetConsoleCtrlHandler(NULL, FALSE);
if (!result) {
git_error_set(GIT_ERROR_OS, "could not set control control handler");
return -1;
}
return 0;
}
......@@ -138,7 +138,7 @@ static int commit_graph_parse_oid_lookup(
struct git_commit_graph_chunk *chunk_oid_lookup)
{
uint32_t i;
git_oid *oid, *prev_oid, zero_oid = {{0}};
unsigned char *oid, *prev_oid, zero_oid[GIT_OID_RAWSZ] = {0};
if (chunk_oid_lookup->offset == 0)
return commit_graph_error("missing OID Lookup chunk");
......@@ -147,10 +147,10 @@ static int commit_graph_parse_oid_lookup(
if (chunk_oid_lookup->length != file->num_commits * GIT_OID_RAWSZ)
return commit_graph_error("OID Lookup chunk has wrong length");
file->oid_lookup = oid = (git_oid *)(data + chunk_oid_lookup->offset);
prev_oid = &zero_oid;
for (i = 0; i < file->num_commits; ++i, ++oid) {
if (git_oid_cmp(prev_oid, oid) >= 0)
file->oid_lookup = oid = (unsigned char *)(data + chunk_oid_lookup->offset);
prev_oid = zero_oid;
for (i = 0; i < file->num_commits; ++i, oid += GIT_OID_RAWSZ) {
if (git_oid_raw_cmp(prev_oid, oid) >= 0)
return commit_graph_error("OID Lookup index is non-monotonic");
prev_oid = oid;
}
......@@ -437,7 +437,7 @@ static int git_commit_graph_entry_get_byindex(
}
commit_data = file->commit_data + pos * (GIT_OID_RAWSZ + 4 * sizeof(uint32_t));
git_oid_cpy(&e->tree_oid, (const git_oid *)commit_data);
git_oid_fromraw(&e->tree_oid, commit_data);
e->parent_indices[0] = ntohl(*((uint32_t *)(commit_data + GIT_OID_RAWSZ)));
e->parent_indices[1] = ntohl(
*((uint32_t *)(commit_data + GIT_OID_RAWSZ + sizeof(uint32_t))));
......@@ -470,7 +470,8 @@ static int git_commit_graph_entry_get_byindex(
e->parent_count++;
}
}
git_oid_cpy(&e->sha1, &file->oid_lookup[pos]);
git_oid_fromraw(&e->sha1, &file->oid_lookup[pos * GIT_OID_RAWSZ]);
return 0;
}
......@@ -514,7 +515,7 @@ int git_commit_graph_entry_find(
{
int pos, found = 0;
uint32_t hi, lo;
const git_oid *current = NULL;
const unsigned char *current = NULL;
GIT_ASSERT_ARG(e);
GIT_ASSERT_ARG(file);
......@@ -528,27 +529,26 @@ int git_commit_graph_entry_find(
if (pos >= 0) {
/* An object matching exactly the oid was found */
found = 1;
current = file->oid_lookup + pos;
current = file->oid_lookup + (pos * GIT_OID_RAWSZ);
} else {
/* No object was found */
/* pos refers to the object with the "closest" oid to short_oid */
pos = -1 - pos;
if (pos < (int)file->num_commits) {
current = file->oid_lookup + pos;
current = file->oid_lookup + (pos * GIT_OID_RAWSZ);
if (!git_oid_ncmp(short_oid, current, len))
if (!git_oid_raw_ncmp(short_oid->id, current, len))
found = 1;
}
}
if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)file->num_commits) {
/* Check for ambiguousity */
const git_oid *next = current + 1;
const unsigned char *next = current + GIT_OID_RAWSZ;
if (!git_oid_ncmp(short_oid, next, len)) {
if (!git_oid_raw_ncmp(short_oid->id, next, len))
found = 2;
}
}
if (!found)
return git_odb__error_notfound(
......@@ -1019,7 +1019,9 @@ static int commit_graph_write(
/* Fill the OID Lookup table. */
git_vector_foreach (&w->commits, i, packed_commit) {
error = git_str_put(&oid_lookup,
(const char *)&packed_commit->sha1, sizeof(git_oid));
(const char *)&packed_commit->sha1.id,
GIT_OID_RAWSZ);
if (error < 0)
goto cleanup;
}
......@@ -1034,8 +1036,9 @@ static int commit_graph_write(
unsigned int parentcount = (unsigned int)git_array_size(packed_commit->parents);
error = git_str_put(&commit_data,
(const char *)&packed_commit->tree_oid,
sizeof(git_oid));
(const char *)&packed_commit->tree_oid.id,
GIT_OID_RAWSZ);
if (error < 0)
goto cleanup;
......
......@@ -36,7 +36,7 @@ typedef struct git_commit_graph_file {
uint32_t num_commits;
/* The OID Lookup table. */
git_oid *oid_lookup;
unsigned char *oid_lookup;
/*
* The Commit Data table. Each entry contains the OID of the commit followed
......
......@@ -74,7 +74,7 @@ struct entry_short {
uint32_t uid;
uint32_t gid;
uint32_t file_size;
git_oid oid;
unsigned char oid[GIT_OID_RAWSZ];
uint16_t flags;
char path[1]; /* arbitrary length */
};
......@@ -88,7 +88,7 @@ struct entry_long {
uint32_t uid;
uint32_t gid;
uint32_t file_size;
git_oid oid;
unsigned char oid[GIT_OID_RAWSZ];
uint16_t flags;
uint16_t flags_extended;
char path[1]; /* arbitrary length */
......@@ -2480,9 +2480,11 @@ static int read_entry(
entry.uid = ntohl(source.uid);
entry.gid = ntohl(source.gid);
entry.file_size = ntohl(source.file_size);
git_oid_cpy(&entry.id, &source.oid);
entry.flags = ntohs(source.flags);
if (git_oid_fromraw(&entry.id, source.oid) < 0)
return -1;
if (entry.flags & GIT_INDEX_ENTRY_EXTENDED) {
uint16_t flags_raw;
size_t flags_offset;
......@@ -2803,9 +2805,7 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry, const cha
ondisk.uid = htonl(entry->uid);
ondisk.gid = htonl(entry->gid);
ondisk.file_size = htonl((uint32_t)entry->file_size);
git_oid_cpy(&ondisk.oid, &entry->id);
git_oid_raw_cpy(ondisk.oid, entry->id.id);
ondisk.flags = htons(entry->flags);
if (entry->flags & GIT_INDEX_ENTRY_EXTENDED) {
......
......@@ -385,7 +385,7 @@ static int check_object_connectivity(git_indexer *idx, const git_rawobj *obj)
size_t i;
git_array_foreach(tree->entries, i, entry)
if (add_expected_oid(idx, entry->oid) < 0)
if (add_expected_oid(idx, &entry->oid) < 0)
goto out;
break;
......@@ -1269,7 +1269,7 @@ int git_indexer_commit(git_indexer *idx, git_indexer_progress *stats)
/* Write out the object names (SHA-1 hashes) */
git_vector_foreach(&idx->objects, i, entry) {
git_filebuf_write(&index_file, &entry->oid, sizeof(git_oid));
git_filebuf_write(&index_file, &entry->oid.id, GIT_OID_RAWSZ);
}
/* Write out the CRC32 values */
......
......@@ -613,7 +613,7 @@ GIT_INLINE(int) tree_iterator_frame_push_neighbors(
break;
if ((error = git_tree_lookup(&tree,
iter->base.repo, entry->tree_entry->oid)) < 0)
iter->base.repo, &entry->tree_entry->oid)) < 0)
break;
if (git_vector_insert(&parent_frame->similar_trees, tree) < 0)
......@@ -659,7 +659,7 @@ GIT_INLINE(int) tree_iterator_frame_push(
int error;
if ((error = git_tree_lookup(&tree,
iter->base.repo, entry->tree_entry->oid)) < 0 ||
iter->base.repo, &entry->tree_entry->oid)) < 0 ||
(error = tree_iterator_frame_init(iter, tree, entry)) < 0)
goto done;
......@@ -740,7 +740,7 @@ static void tree_iterator_set_current(
iter->entry.mode = tree_entry->attr;
iter->entry.path = iter->entry_path.ptr;
git_oid_cpy(&iter->entry.id, tree_entry->oid);
git_oid_cpy(&iter->entry.id, &tree_entry->oid);
}
static int tree_iterator_advance(const git_index_entry **out, git_iterator *i)
......
......@@ -115,7 +115,7 @@ static int midx_parse_oid_lookup(
struct git_midx_chunk *chunk_oid_lookup)
{
uint32_t i;
git_oid *oid, *prev_oid, zero_oid = {{0}};
unsigned char *oid, *prev_oid, zero_oid[GIT_OID_RAWSZ] = {0};
if (chunk_oid_lookup->offset == 0)
return midx_error("missing OID Lookup chunk");
......@@ -124,10 +124,10 @@ static int midx_parse_oid_lookup(
if (chunk_oid_lookup->length != idx->num_objects * GIT_OID_RAWSZ)
return midx_error("OID Lookup chunk has wrong length");
idx->oid_lookup = oid = (git_oid *)(data + chunk_oid_lookup->offset);
prev_oid = &zero_oid;
for (i = 0; i < idx->num_objects; ++i, ++oid) {
if (git_oid_cmp(prev_oid, oid) >= 0)
idx->oid_lookup = oid = (unsigned char *)(data + chunk_oid_lookup->offset);
prev_oid = zero_oid;
for (i = 0; i < idx->num_objects; ++i, oid += GIT_OID_RAWSZ) {
if (git_oid_raw_cmp(prev_oid, oid) >= 0)
return midx_error("OID Lookup index is non-monotonic");
prev_oid = oid;
}
......@@ -179,7 +179,6 @@ int git_midx_parse(
uint32_t i;
off64_t last_chunk_offset, chunk_offset, trailer_offset;
size_t checksum_size;
unsigned char checksum[GIT_HASH_SHA1_SIZE];
int error;
struct git_midx_chunk chunk_packfile_names = {0},
chunk_oid_fanout = {0},
......@@ -217,11 +216,6 @@ int git_midx_parse(
return midx_error("wrong index size");
memcpy(idx->checksum, data + trailer_offset, checksum_size);
if (git_hash_buf(checksum, data, (size_t)trailer_offset, GIT_HASH_ALGORITHM_SHA1) < 0)
return midx_error("could not calculate signature");
if (memcmp(checksum, idx->checksum, checksum_size) != 0)
return midx_error("index signature mismatch");
chunk_hdr = data + sizeof(struct git_midx_header);
last_chunk = NULL;
for (i = 0; i < hdr->chunks; ++i, chunk_hdr += 12) {
......@@ -389,7 +383,7 @@ int git_midx_entry_find(
int pos, found = 0;
size_t pack_index;
uint32_t hi, lo;
const git_oid *current = NULL;
unsigned char *current = NULL;
const unsigned char *object_offset;
off64_t offset;
......@@ -403,27 +397,26 @@ int git_midx_entry_find(
if (pos >= 0) {
/* An object matching exactly the oid was found */
found = 1;
current = idx->oid_lookup + pos;
current = idx->oid_lookup + (pos * GIT_OID_RAWSZ);
} else {
/* No object was found */
/* pos refers to the object with the "closest" oid to short_oid */
pos = -1 - pos;
if (pos < (int)idx->num_objects) {
current = idx->oid_lookup + pos;
current = idx->oid_lookup + (pos * GIT_OID_RAWSZ);
if (!git_oid_ncmp(short_oid, current, len))
if (!git_oid_raw_ncmp(short_oid->id, current, len))
found = 1;
}
}
if (found && len != GIT_OID_HEXSZ && pos + 1 < (int)idx->num_objects) {
/* Check for ambiguousity */
const git_oid *next = current + 1;
const unsigned char *next = current + GIT_OID_RAWSZ;
if (!git_oid_ncmp(short_oid, next, len)) {
if (!git_oid_raw_ncmp(short_oid->id, next, len))
found = 2;
}
}
if (!found)
return git_odb__error_notfound("failed to find offset for multi-pack index entry", short_oid, len);
......@@ -432,8 +425,8 @@ int git_midx_entry_find(
object_offset = idx->object_offsets + pos * 8;
offset = ntohl(*((uint32_t *)(object_offset + 4)));
if (offset & 0x80000000) {
uint32_t object_large_offsets_pos = offset & 0x7fffffff;
if (idx->object_large_offsets && offset & 0x80000000) {
uint32_t object_large_offsets_pos = (uint32_t) (offset ^ 0x80000000);
const unsigned char *object_large_offsets_index = idx->object_large_offsets;
/* Make sure we're not being sent out of bounds */
......@@ -450,7 +443,7 @@ int git_midx_entry_find(
return midx_error("invalid index into the packfile names table");
e->pack_index = pack_index;
e->offset = offset;
git_oid_cpy(&e->sha1, current);
git_oid_fromraw(&e->sha1, current);
return 0;
}
......@@ -459,13 +452,17 @@ int git_midx_foreach_entry(
git_odb_foreach_cb cb,
void *data)
{
git_oid oid;
size_t i;
int error;
GIT_ASSERT_ARG(idx);
for (i = 0; i < idx->num_objects; ++i) {
if ((error = cb(&idx->oid_lookup[i], data)) != 0)
if ((error = git_oid_fromraw(&oid, &idx->oid_lookup[i * GIT_OID_RAWSZ])) < 0)
return error;
if ((error = cb(&oid, data)) != 0)
return git_error_set_after_callback(error);
}
......@@ -751,7 +748,7 @@ static int midx_write(
/* Fill the OID Lookup table. */
git_vector_foreach (&object_entries, i, entry) {
error = git_str_put(&oid_lookup, (const char *)&entry->sha1, sizeof(entry->sha1));
error = git_str_put(&oid_lookup, (char *)&entry->sha1.id, GIT_OID_RAWSZ);
if (error < 0)
goto cleanup;
}
......
......@@ -17,6 +17,7 @@
#include "map.h"
#include "mwindow.h"
#include "odb.h"
#include "oid.h"
/*
* A multi-pack-index file.
......@@ -40,7 +41,7 @@ typedef struct git_midx_file {
uint32_t num_objects;
/* The OID Lookup table. */
git_oid *oid_lookup;
unsigned char *oid_lookup;
/* The Object Offsets table. Each entry has two 4-byte fields with the pack index and the offset. */
const unsigned char *object_offsets;
......
......@@ -187,8 +187,7 @@ int git_oid_fromraw(git_oid *out, const unsigned char *raw)
int git_oid_cpy(git_oid *out, const git_oid *src)
{
memcpy(out->id, src->id, sizeof(out->id));
return 0;
return git_oid_raw_cpy(out->id, src->id);
}
int git_oid_cmp(const git_oid *a, const git_oid *b)
......@@ -203,25 +202,7 @@ int git_oid_equal(const git_oid *a, const git_oid *b)
int git_oid_ncmp(const git_oid *oid_a, const git_oid *oid_b, size_t len)
{
const unsigned char *a = oid_a->id;
const unsigned char *b = oid_b->id;
if (len > GIT_OID_HEXSZ)
len = GIT_OID_HEXSZ;
while (len > 1) {
if (*a != *b)
return 1;
a++;
b++;
len -= 2;
};
if (len)
if ((*a ^ *b) & 0xf0)
return 1;
return 0;
return git_oid_raw_ncmp(oid_a->id, oid_b->id, len);
}
int git_oid_strcmp(const git_oid *oid_a, const char *str)
......
......@@ -25,11 +25,44 @@ extern const git_oid git_oid__empty_tree_sha1;
*/
char *git_oid_allocfmt(const git_oid *id);
GIT_INLINE(int) git_oid__hashcmp(const unsigned char *sha1, const unsigned char *sha2)
GIT_INLINE(int) git_oid_raw_ncmp(
const unsigned char *sha1,
const unsigned char *sha2,
size_t len)
{
if (len > GIT_OID_HEXSZ)
len = GIT_OID_HEXSZ;
while (len > 1) {
if (*sha1 != *sha2)
return 1;
sha1++;
sha2++;
len -= 2;
};
if (len)
if ((*sha1 ^ *sha2) & 0xf0)
return 1;
return 0;
}
GIT_INLINE(int) git_oid_raw_cmp(
const unsigned char *sha1,
const unsigned char *sha2)
{
return memcmp(sha1, sha2, GIT_OID_RAWSZ);
}
GIT_INLINE(int) git_oid_raw_cpy(
unsigned char *dst,
const unsigned char *src)
{
memcpy(dst, src, GIT_OID_RAWSZ);
return 0;
}
/*
* Compare two oid structures.
*
......@@ -39,7 +72,7 @@ GIT_INLINE(int) git_oid__hashcmp(const unsigned char *sha1, const unsigned char
*/
GIT_INLINE(int) git_oid__cmp(const git_oid *a, const git_oid *b)
{
return git_oid__hashcmp(a->id, b->id);
return git_oid_raw_cmp(a->id, b->id);
}
GIT_INLINE(void) git_oid__cpy_prefix(
......
......@@ -19,7 +19,7 @@ __KHASH_TYPE(oid, const git_oid *, void *)
GIT_INLINE(khint_t) git_oidmap_hash(const git_oid *oid)
{
khint_t h;
memcpy(&h, oid, sizeof(khint_t));
memcpy(&h, oid->id, sizeof(khint_t));
return h;
}
......
......@@ -1001,13 +1001,14 @@ int get_delta_base(
base_offset = delta_obj_offset - unsigned_base_offset;
*curpos += used;
} else if (type == GIT_OBJECT_REF_DELTA) {
git_oid base_oid;
git_oid_fromraw(&base_oid, base_info);
/* If we have the cooperative cache, search in it first */
if (p->has_cache) {
struct git_pack_entry *entry;
git_oid oid;
git_oid_fromraw(&oid, base_info);
if ((entry = git_oidmap_get(p->idx_cache, &oid)) != NULL) {
if ((entry = git_oidmap_get(p->idx_cache, &base_oid)) != NULL) {
if (entry->offset == 0)
return packfile_error("delta offset is zero");
......@@ -1024,7 +1025,7 @@ int get_delta_base(
}
/* The base entry _must_ be in the same pack */
if (pack_entry_find_offset(&base_offset, &unused, p, (git_oid *)base_info, GIT_OID_HEXSZ) < 0)
if (pack_entry_find_offset(&base_offset, &unused, p, &base_oid, GIT_OID_HEXSZ) < 0)
return packfile_error("base entry delta is not in the same pack");
*curpos += 20;
} else
......@@ -1082,7 +1083,7 @@ static int packfile_open_locked(struct git_pack_file *p)
{
struct stat st;
struct git_pack_header hdr;
git_oid sha1;
unsigned char sha1[GIT_OID_RAWSZ];
unsigned char *idx_sha1;
if (pack_index_open_locked(p) < 0)
......@@ -1130,12 +1131,12 @@ static int packfile_open_locked(struct git_pack_file *p)
/* Verify the pack matches its index. */
if (p->num_objects != ntohl(hdr.hdr_entries) ||
p_pread(p->mwf.fd, sha1.id, GIT_OID_RAWSZ, p->mwf.size - GIT_OID_RAWSZ) < 0)
p_pread(p->mwf.fd, sha1, GIT_OID_RAWSZ, p->mwf.size - GIT_OID_RAWSZ) < 0)
goto cleanup;
idx_sha1 = ((unsigned char *)p->index_map.data) + p->index_map.len - 40;
if (git_oid__cmp(&sha1, (git_oid *)idx_sha1) != 0)
if (git_oid_raw_cmp(sha1, idx_sha1) != 0)
goto cleanup;
if (git_mwindow_file_register(&p->mwf) < 0)
......@@ -1340,10 +1341,14 @@ int git_pack_foreach_entry(
}
git_vector_free(&offsets);
p->oids = (git_oid **)git_vector_detach(NULL, NULL, &oids);
p->oids = (unsigned char **)git_vector_detach(NULL, NULL, &oids);
}
/* We need to copy the OIDs to another array before we relinquish the lock to avoid races. */
/*
* We need to copy the OIDs to another array before we
* relinquish the lock to avoid races. We can also take
* this opportunity to put them into normal form.
*/
git_array_init_to_size(oids, p->num_objects);
if (!oids.ptr) {
git_mutex_unlock(&p->lock);
......@@ -1357,7 +1362,7 @@ int git_pack_foreach_entry(
git_array_clear(oids);
GIT_ERROR_CHECK_ALLOC(oid);
}
git_oid_cpy(oid, p->oids[i]);
git_oid_fromraw(oid, p->oids[i]);
}
git_mutex_unlock(&p->lock);
......@@ -1380,7 +1385,7 @@ int git_pack_foreach_entry_offset(
{
const unsigned char *index;
off64_t current_offset;
const git_oid *current_oid;
git_oid current_oid;
uint32_t i;
int error = 0;
......@@ -1422,8 +1427,9 @@ int git_pack_foreach_entry_offset(
current_offset = (((off64_t)ntohl(*((uint32_t *)(large_offset_ptr + 0)))) << 32) |
ntohl(*((uint32_t *)(large_offset_ptr + 4)));
}
current_oid = (const git_oid *)(index + 20 * i);
if ((error = cb(current_oid, current_offset, data)) != 0) {
git_oid_fromraw(&current_oid, (index + 20 * i));
if ((error = cb(&current_oid, current_offset, data)) != 0) {
error = git_error_set_after_callback(error);
goto cleanup;
}
......@@ -1431,8 +1437,8 @@ int git_pack_foreach_entry_offset(
} else {
for (i = 0; i < p->num_objects; i++) {
current_offset = ntohl(*(const uint32_t *)(index + 24 * i));
current_oid = (const git_oid *)(index + 24 * i + 4);
if ((error = cb(current_oid, current_offset, data)) != 0) {
git_oid_fromraw(&current_oid, (index + 24 * i + 4));
if ((error = cb(&current_oid, current_offset, data)) != 0) {
error = git_error_set_after_callback(error);
goto cleanup;
}
......@@ -1451,7 +1457,7 @@ int git_pack__lookup_sha1(const void *oid_lookup_table, size_t stride, unsigned
while (lo < hi) {
unsigned mi = (lo + hi) / 2;
int cmp = git_oid__hashcmp(base + mi * stride, oid_prefix);
int cmp = git_oid_raw_cmp(base + mi * stride, oid_prefix);
if (!cmp)
return mi;
......@@ -1530,7 +1536,7 @@ static int pack_entry_find_offset(
if (pos < (int)p->num_objects) {
current = index + pos * stride;
if (!git_oid_ncmp(short_oid, (const git_oid *)current, len))
if (!git_oid_raw_ncmp(short_oid->id, current, len))
found = 1;
}
}
......@@ -1539,7 +1545,7 @@ static int pack_entry_find_offset(
/* Check for ambiguousity */
const unsigned char *next = current + stride;
if (!git_oid_ncmp(short_oid, (const git_oid *)next, len)) {
if (!git_oid_raw_ncmp(short_oid->id, next, len)) {
found = 2;
}
}
......
......@@ -19,6 +19,7 @@
#include "offmap.h"
#include "oidmap.h"
#include "zstream.h"
#include "oid.h"
/**
* Function type for callbacks from git_pack_foreach_entry_offset.
......@@ -104,7 +105,7 @@ struct git_pack_file {
git_time_t mtime;
unsigned pack_local:1, pack_keep:1, has_cache:1;
git_oidmap *idx_cache;
git_oid **oids;
unsigned char **oids;
git_pack_cache bases; /* delta base cache */
......
......@@ -740,7 +740,7 @@ static int packed_lookup(
return 0;
}
}
return GIT_ENOTFOUND;
return ref_error_notfound(ref_name);
parse_failed:
git_error_set(GIT_ERROR_REFERENCE, "corrupted packed references file");
......
......@@ -1830,7 +1830,7 @@ static int update_one_tip(
}
if (error == GIT_ENOTFOUND) {
memset(&old, 0, GIT_OID_RAWSZ);
memset(&old, 0, sizeof(git_oid));
error = 0;
if (autotag && (error = git_vector_insert(update_heads, head)) < 0)
......
......@@ -263,7 +263,7 @@ static void write_tree(git_str *out, git_tree_cache *tree)
git_str_printf(out, "%s%c%"PRIdZ" %"PRIuZ"\n", tree->name, 0, tree->entry_count, tree->children_count);
if (tree->entry_count != -1)
git_str_put(out, (const char *) &tree->oid, GIT_OID_RAWSZ);
git_str_put(out, (char *)&tree->oid.id, GIT_OID_RAWSZ);
for (i = 0; i < tree->children_count; i++)
write_tree(out, tree->children[i]);
......
......@@ -82,6 +82,7 @@ int git_tree_entry_cmp(const git_tree_entry *e1, const git_tree_entry *e2)
static git_tree_entry *alloc_entry(const char *filename, size_t filename_len, const git_oid *id)
{
git_tree_entry *entry = NULL;
char *filename_ptr;
size_t tree_len;
TREE_ENTRY_CHECK_NAMELEN(filename_len);
......@@ -95,21 +96,13 @@ static git_tree_entry *alloc_entry(const char *filename, size_t filename_len, co
if (!entry)
return NULL;
{
char *filename_ptr;
void *id_ptr;
filename_ptr = ((char *) entry) + sizeof(git_tree_entry);
memcpy(filename_ptr, filename, filename_len);
entry->filename = filename_ptr;
id_ptr = filename_ptr + filename_len + 1;
git_oid_cpy(id_ptr, id);
entry->oid = id_ptr;
}
entry->filename_len = (uint16_t)filename_len;
git_oid_cpy(&entry->oid, id);
return entry;
}
......@@ -231,7 +224,7 @@ int git_tree_entry_dup(git_tree_entry **dest, const git_tree_entry *source)
GIT_ASSERT_ARG(source);
cpy = alloc_entry(source->filename, source->filename_len, source->oid);
cpy = alloc_entry(source->filename, source->filename_len, &source->oid);
if (cpy == NULL)
return -1;
......@@ -269,7 +262,7 @@ const char *git_tree_entry_name(const git_tree_entry *entry)
const git_oid *git_tree_entry_id(const git_tree_entry *entry)
{
GIT_ASSERT_ARG_WITH_RETVAL(entry, NULL);
return entry->oid;
return &entry->oid;
}
git_object_t git_tree_entry_type(const git_tree_entry *entry)
......@@ -292,7 +285,7 @@ int git_tree_entry_to_object(
GIT_ASSERT_ARG(entry);
GIT_ASSERT_ARG(object_out);
return git_object_lookup(object_out, repo, entry->oid, GIT_OBJECT_ANY);
return git_object_lookup(object_out, repo, &entry->oid, GIT_OBJECT_ANY);
}
static const git_tree_entry *entry_fromname(
......@@ -331,7 +324,7 @@ const git_tree_entry *git_tree_entry_byid(
GIT_ASSERT_ARG_WITH_RETVAL(tree, NULL);
git_array_foreach(tree->entries, i, e) {
if (memcmp(&e->oid->id, &id->id, sizeof(id->id)) == 0)
if (git_oid_equal(&e->oid, id))
return e;
}
......@@ -432,7 +425,7 @@ int git_tree__parse_raw(void *_tree, const char *data, size_t size)
entry->attr = attr;
entry->filename_len = (uint16_t)filename_len;
entry->filename = buffer;
entry->oid = (git_oid *) ((char *) buffer + filename_len + 1);
git_oid_fromraw(&entry->oid, ((unsigned char *) buffer + filename_len + 1));
}
buffer += filename_len + 1;
......@@ -536,7 +529,7 @@ static int git_treebuilder__write_with_buffer(
git_str_printf(buf, "%o ", entry->attr);
git_str_put(buf, entry->filename, entry->filename_len + 1);
git_str_put(buf, (char *)entry->oid->id, GIT_OID_RAWSZ);
git_str_put(buf, (char *)entry->oid.id, GIT_OID_RAWSZ);
if (git_str_oom(buf)) {
error = -1;
......@@ -765,7 +758,7 @@ int git_treebuilder_new(
git_array_foreach(source->entries, i, entry_src) {
if (append_entry(
bld, entry_src->filename,
entry_src->oid,
&entry_src->oid,
entry_src->attr,
false) < 0)
goto on_error;
......@@ -798,7 +791,7 @@ int git_treebuilder_insert(
return error;
if ((entry = git_strmap_get(bld->map, filename)) != NULL) {
git_oid_cpy((git_oid *) entry->oid, id);
git_oid_cpy(&entry->oid, id);
} else {
entry = alloc_entry(filename, strlen(filename), id);
GIT_ERROR_CHECK_ALLOC(entry);
......@@ -954,7 +947,7 @@ int git_tree_entry_bypath(
return git_tree_entry_dup(entry_out, entry);
}
if (git_tree_lookup(&subtree, root->object.repo, entry->oid) < 0)
if (git_tree_lookup(&subtree, root->object.repo, &entry->oid) < 0)
return -1;
error = git_tree_entry_bypath(
......@@ -995,7 +988,7 @@ static int tree_walk(
git_tree *subtree;
size_t path_len = git_str_len(path);
error = git_tree_lookup(&subtree, tree->object.repo, entry->oid);
error = git_tree_lookup(&subtree, tree->object.repo, &entry->oid);
if (error < 0)
break;
......
......@@ -19,7 +19,7 @@
struct git_tree_entry {
uint16_t attr;
uint16_t filename_len;
const git_oid *oid;
git_oid oid;
const char *filename;
};
......
......@@ -268,7 +268,7 @@ static void check_tree_entry(
cl_git_pass(git_iterator_current_tree_entry(&te, i));
cl_assert(te);
cl_assert(git_oid_streq(te->oid, oid) == 0);
cl_assert(git_oid_streq(&te->oid, oid) == 0);
cl_git_pass(git_iterator_current(&ie, i));
......
......@@ -24,20 +24,23 @@ static char *bye_text = "bye world\n";
void test_object_raw_hash__hash_by_blocks(void)
{
git_hash_ctx ctx;
unsigned char hash[GIT_HASH_SHA1_SIZE];
git_oid id1, id2;
cl_git_pass(git_hash_ctx_init(&ctx, GIT_HASH_ALGORITHM_SHA1));
/* should already be init'd */
cl_git_pass(git_hash_update(&ctx, hello_text, strlen(hello_text)));
cl_git_pass(git_hash_final(id2.id, &ctx));
cl_git_pass(git_hash_final(hash, &ctx));
cl_git_pass(git_oid_fromraw(&id2, hash));
cl_git_pass(git_oid_fromstr(&id1, hello_id));
cl_assert(git_oid_cmp(&id1, &id2) == 0);
/* reinit should permit reuse */
cl_git_pass(git_hash_init(&ctx));
cl_git_pass(git_hash_update(&ctx, bye_text, strlen(bye_text)));
cl_git_pass(git_hash_final(id2.id, &ctx));
cl_git_pass(git_hash_final(hash, &ctx));
cl_git_pass(git_oid_fromraw(&id2, hash));
cl_git_pass(git_oid_fromstr(&id1, bye_id));
cl_assert(git_oid_cmp(&id1, &id2) == 0);
......@@ -47,9 +50,11 @@ void test_object_raw_hash__hash_by_blocks(void)
void test_object_raw_hash__hash_buffer_in_single_call(void)
{
git_oid id1, id2;
unsigned char hash[GIT_HASH_SHA1_SIZE];
cl_git_pass(git_oid_fromstr(&id1, hello_id));
git_hash_buf(id2.id, hello_text, strlen(hello_text), GIT_HASH_ALGORITHM_SHA1);
cl_git_pass(git_hash_buf(hash, hello_text, strlen(hello_text), GIT_HASH_ALGORITHM_SHA1));
cl_git_pass(git_oid_fromraw(&id2, hash));
cl_assert(git_oid_cmp(&id1, &id2) == 0);
}
......
......@@ -28,12 +28,15 @@ static int insert_sequential_oids(
int i, min_len = 0;
char numbuf[16];
git_oid oid;
unsigned char hashbuf[GIT_HASH_SHA1_SIZE];
char **oids = git__calloc(n, sizeof(char *));
cl_assert(oids != NULL);
for (i = 0; i < n; ++i) {
p_snprintf(numbuf, sizeof(numbuf), "%u", (unsigned int)i);
git_hash_buf(oid.id, numbuf, strlen(numbuf), GIT_HASH_ALGORITHM_SHA1);
git_hash_buf(hashbuf, numbuf, strlen(numbuf), GIT_HASH_ALGORITHM_SHA1);
git_oid_fromraw(&oid, hashbuf);
oids[i] = git__malloc(GIT_OID_HEXSZ + 1);
cl_assert(oids[i]);
......
......@@ -40,7 +40,7 @@ static void assert_tree_parses(const char *data, size_t datalen,
cl_assert(entry = git_tree_entry_byname(tree, expected->filename));
cl_assert_equal_s(expected->filename, entry->filename);
cl_assert_equal_i(expected->attr, entry->attr);
cl_assert_equal_oid(&oid, entry->oid);
cl_assert_equal_oid(&oid, &entry->oid);
}
git_object_free(&tree->object);
......
......@@ -68,7 +68,7 @@ static void seed_packbuilder(void)
cl_git_pass(git_revwalk_push_ref(_revwalker, "HEAD"));
while (git_revwalk_next(&oid, _revwalker) == 0) {
o = git__malloc(GIT_OID_RAWSZ);
o = git__malloc(sizeof(git_oid));
cl_assert(o != NULL);
git_oid_cpy(o, &oid);
cl_git_pass(git_vector_insert(&_commits, o));
......
......@@ -399,8 +399,6 @@ void test_refs_revparse__date(void)
* a65fedf HEAD@{1335806603 -0900}: commit:
* be3563a HEAD@{1335806563 -0700}: clone: from /Users/ben/src/libgit2/tests/resour
*/
test_object("HEAD@{10 years ago}", "be3563ae3f795b2b4353bcce3a527ad0a4f7f644");
test_object("HEAD@{1 second}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("HEAD@{1 second ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
test_object("HEAD@{2 days ago}", "a65fedf39aefe402d3bb6e24df4d4f5fe4547750");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment