python-pygit2/0001-Update-to-libgit2-v0.23.patch
Igor Gnatenko 682256b811 Cherry-pick patch for 0.23.0 support
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
2015-07-31 13:29:53 +03:00

1098 lines
40 KiB
Diff

From 81520c9c626e092bc45f9fc8ba138eefa4d1beb2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= <cmn@dwim.me>
Date: Mon, 8 Jun 2015 12:19:01 +0200
Subject: [PATCH] Update to libgit2 v0.23
---
.travis.sh | 2 +-
pygit2/__init__.py | 8 +--
pygit2/config.py | 43 ++++++++++-----
pygit2/decl.h | 129 +++++++++++++++++++++++++++++++--------------
pygit2/remote.py | 144 ++++++++++++++++++---------------------------------
pygit2/repository.py | 63 +++++++++++-----------
pygit2/utils.py | 5 ++
src/branch.c | 2 +-
src/pygit2.c | 3 +-
src/reference.c | 22 +++-----
src/repository.c | 12 ++---
src/types.h | 4 +-
test/test_merge.py | 2 +-
test/test_refs.py | 3 +-
test/test_remote.py | 65 ++++++-----------------
15 files changed, 252 insertions(+), 255 deletions(-)
diff --git a/pygit2/__init__.py b/pygit2/__init__.py
index d963bca..709adca 100644
--- a/pygit2/__init__.py
+++ b/pygit2/__init__.py
@@ -278,12 +278,12 @@ def clone_repository(
opts.bare = bare
if credentials:
- opts.remote_callbacks.credentials = _credentials_cb
- opts.remote_callbacks.payload = d_handle
+ opts.fetch_opts.callbacks.credentials = _credentials_cb
+ opts.fetch_opts.callbacks.payload = d_handle
if certificate:
- opts.remote_callbacks.certificate_check = _certificate_cb
- opts.remote_callbacks.payload = d_handle
+ opts.fetch_opts.callbacks.certificate_check = _certificate_cb
+ opts.fetch_opts.callbacks.payload = d_handle
err = C.git_clone(crepo, to_bytes(url), to_bytes(path), opts)
diff --git a/pygit2/config.py b/pygit2/config.py
index 33cc6da..a01fdf6 100644
--- a/pygit2/config.py
+++ b/pygit2/config.py
@@ -101,19 +101,19 @@ class Config(object):
def _get(self, key):
assert_string(key, "key")
- cstr = ffi.new('char **')
- err = C.git_config_get_string(cstr, self._config, to_bytes(key))
+ entry = ffi.new('git_config_entry **')
+ err = C.git_config_get_entry(entry, self._config, to_bytes(key))
- return err, cstr
+ return err, ConfigEntry._from_c(entry[0])
- def _get_string(self, key):
- err, cstr = self._get(key)
+ def _get_entry(self, key):
+ err, entry = self._get(key)
if err == C.GIT_ENOTFOUND:
raise KeyError(key)
check_error(err)
- return cstr[0]
+ return entry
def __contains__(self, key):
err, cstr = self._get(key)
@@ -126,9 +126,9 @@ class Config(object):
return True
def __getitem__(self, key):
- val = self._get_string(key)
+ entry = self._get_entry(key)
- return ffi.string(val).decode('utf-8')
+ return ffi.string(entry.value).decode('utf-8')
def __setitem__(self, key, value):
assert_string(key, "key")
@@ -192,9 +192,10 @@ class Config(object):
Truthy values are: 'true', 1, 'on' or 'yes'. Falsy values are: 'false',
0, 'off' and 'no'
"""
- val = self._get_string(key)
+
+ entry = self._get_entry(key)
res = ffi.new('int *')
- err = C.git_config_parse_bool(res, val)
+ err = C.git_config_parse_bool(res, entry.value)
check_error(err)
return res[0] != 0
@@ -206,9 +207,10 @@ class Config(object):
A value can have a suffix 'k', 'm' or 'g' which stand for 'kilo',
'mega' and 'giga' respectively.
"""
- val = self._get_string(key)
+
+ entry = self._get_entry(key)
res = ffi.new('int64_t *')
- err = C.git_config_parse_int64(res, val)
+ err = C.git_config_parse_int64(res, entry.value)
check_error(err)
return res[0]
@@ -283,3 +285,20 @@ class Config(object):
"""Return a <Config> object representing the global configuration file.
"""
return Config._from_found_config(C.git_config_find_xdg)
+
+class ConfigEntry(object):
+ """An entry in a configuation object
+ """
+
+ @classmethod
+ def _from_c(cls, ptr):
+ entry = cls.__new__(cls)
+ entry._entry = ptr
+ return entry
+
+ def __del__(self):
+ C.git_config_entry_free(self._entry)
+
+ @property
+ def value(self):
+ return self._entry.value
diff --git a/pygit2/decl.h b/pygit2/decl.h
index 2ea73f2..61afe33 100644
--- a/pygit2/decl.h
+++ b/pygit2/decl.h
@@ -1,6 +1,7 @@
typedef ... git_repository;
typedef ... git_submodule;
typedef ... git_remote;
+typedef ... git_transport;
typedef ... git_refspec;
typedef ... git_cred;
typedef ... git_object;
@@ -51,7 +52,7 @@ typedef enum {
GIT_EUNMERGED = -10,
GIT_ENONFASTFORWARD = -11,
GIT_EINVALIDSPEC = -12,
- GIT_EMERGECONFLICT = -13,
+ GIT_ECONFLICT = -13,
GIT_ELOCKED = -14,
GIT_PASSTHROUGH = -30,
@@ -118,6 +119,7 @@ typedef enum {
} git_credtype_t;
typedef enum git_cert_t {
+ GIT_CERT_NONE,
GIT_CERT_X509,
GIT_CERT_HOSTKEY_LIBSSH2,
} git_cert_t;
@@ -165,6 +167,16 @@ typedef int (*git_push_transfer_progress)(
size_t bytes,
void* payload);
+typedef struct {
+ char *src_refname;
+ char *dst_refname;
+ git_oid src;
+ git_oid dst;
+} git_push_update;
+
+typedef int (*git_push_negotiation)(const git_push_update **updates, size_t len, void *payload);
+typedef int (*git_transport_cb)(git_transport **out, git_remote *owner, void *param);
+
struct git_remote_callbacks {
unsigned int version;
git_transport_message_cb sideband_progress;
@@ -173,19 +185,51 @@ struct git_remote_callbacks {
git_transport_certificate_check_cb certificate_check;
git_transfer_progress_cb transfer_progress;
int (*update_tips)(const char *refname, const git_oid *a, const git_oid *b, void *data);
- git_packbuilder_progress pack_progress;
+ git_packbuilder_progress pack_progress;
git_push_transfer_progress push_transfer_progress;
int (*push_update_reference)(const char *refname, const char *status, void *data);
+ git_push_negotiation push_negotiation;
+ git_transport_cb transport;
void *payload;
};
+#define GIT_REMOTE_CALLBACKS_VERSION ...
+
typedef struct git_remote_callbacks git_remote_callbacks;
typedef struct {
unsigned int version;
unsigned int pb_parallelism;
+ git_remote_callbacks callbacks;
} git_push_options;
+#define GIT_PUSH_OPTIONS_VERSION ...
+int git_push_init_options(git_push_options *opts, unsigned int version);
+
+typedef enum {
+ GIT_FETCH_PRUNE_UNSPECIFIED,
+ GIT_FETCH_PRUNE,
+ GIT_FETCH_NO_PRUNE,
+} git_fetch_prune_t;
+
+typedef enum {
+ GIT_REMOTE_DOWNLOAD_TAGS_UNSPECIFIED = 0,
+ GIT_REMOTE_DOWNLOAD_TAGS_AUTO,
+ GIT_REMOTE_DOWNLOAD_TAGS_NONE,
+ GIT_REMOTE_DOWNLOAD_TAGS_ALL,
+} git_remote_autotag_option_t;
+
+typedef struct {
+ int version;
+ git_remote_callbacks callbacks;
+ git_fetch_prune_t prune;
+ int update_fetchhead;
+ git_remote_autotag_option_t download_tags;
+} git_fetch_options;
+
+#define GIT_FETCH_OPTIONS_VERSION ...
+int git_fetch_init_options(git_fetch_options *opts, unsigned int version);
+
int git_remote_list(git_strarray *out, git_repository *repo);
int git_remote_lookup(git_remote **out, git_repository *repo, const char *name);
int git_remote_create(
@@ -201,24 +245,20 @@ const char * git_remote_name(const git_remote *remote);
int git_remote_rename(git_strarray *problems, git_repository *repo, const char *name, const char *new_name);
const char * git_remote_url(const git_remote *remote);
-int git_remote_set_url(git_remote *remote, const char* url);
+int git_remote_set_url(git_repository *repo, const char *remote, const char* url);
const char * git_remote_pushurl(const git_remote *remote);
-int git_remote_set_pushurl(git_remote *remote, const char* url);
-int git_remote_fetch(git_remote *remote, const git_strarray *refspecs, const git_signature *signature, const char *reflog_message);
-int git_remote_push(git_remote *remote, git_strarray *refspecs, const git_push_options *opts, const git_signature *signature, const char *reflog_message);
+int git_remote_set_pushurl(git_repository *repo, const char *remote, const char* url);
+int git_remote_fetch(git_remote *remote, const git_strarray *refspecs, const git_fetch_options *opts, const char *reflog_message);
+int git_remote_push(git_remote *remote, const git_strarray *refspecs, const git_push_options *opts);
const git_transfer_progress * git_remote_stats(git_remote *remote);
-int git_remote_add_push(git_remote *remote, const char *refspec);
-int git_remote_add_fetch(git_remote *remote, const char *refspec);
-int git_remote_save(const git_remote *remote);
-int git_remote_set_callbacks(git_remote *remote, const git_remote_callbacks *callbacks);
+int git_remote_add_push(git_repository *repo, const char *remote, const char *refspec);
+int git_remote_add_fetch(git_repository *repo, const char *remote, const char *refspec);
int git_remote_init_callbacks(git_remote_callbacks *opts, unsigned int version);
size_t git_remote_refspec_count(git_remote *remote);
const git_refspec * git_remote_get_refspec(git_remote *remote, size_t n);
int git_remote_get_fetch_refspecs(git_strarray *array, git_remote *remote);
-int git_remote_set_fetch_refspecs(git_remote *remote, git_strarray *array);
int git_remote_get_push_refspecs(git_strarray *array, git_remote *remote);
-int git_remote_set_push_refspecs(git_remote *remote, git_strarray *array);
void git_remote_free(git_remote *remote);
@@ -253,13 +293,12 @@ int git_cred_ssh_key_from_agent(
*/
typedef enum {
- GIT_SUBMODULE_IGNORE_RESET = -1,
+ GIT_SUBMODULE_IGNORE_UNSPECIFIED = -1,
GIT_SUBMODULE_IGNORE_NONE = 1,
GIT_SUBMODULE_IGNORE_UNTRACKED = 2,
GIT_SUBMODULE_IGNORE_DIRTY = 3,
GIT_SUBMODULE_IGNORE_ALL = 4,
- GIT_SUBMODULE_IGNORE_DEFAULT = 0
} git_submodule_ignore_t;
typedef enum {
@@ -348,32 +387,37 @@ typedef void (*git_checkout_progress_cb)(
size_t total_steps,
void *payload);
+typedef struct {
+ size_t mkdir_calls;
+ size_t stat_calls;
+ size_t chmod_calls;
+} git_checkout_perfdata;
+
+typedef void (*git_checkout_perfdata_cb)(
+ const git_checkout_perfdata *perfdata,
+ void *payload);
+
typedef struct git_checkout_options {
unsigned int version;
-
unsigned int checkout_strategy;
-
int disable_filters;
unsigned int dir_mode;
unsigned int file_mode;
int file_open_flags;
-
unsigned int notify_flags;
git_checkout_notify_cb notify_cb;
void *notify_payload;
-
git_checkout_progress_cb progress_cb;
void *progress_payload;
-
git_strarray paths;
-
git_tree *baseline;
-
+ git_index *baseline_index;
const char *target_directory;
-
const char *ancestor_label;
const char *our_label;
const char *their_label;
+ git_checkout_perfdata_cb perfdata_cb;
+ void *perfdata_payload;
} git_checkout_options;
int git_checkout_init_options(git_checkout_options *opts, unsigned int version);
@@ -408,11 +452,10 @@ typedef enum {
typedef struct git_clone_options {
unsigned int version;
git_checkout_options checkout_opts;
- git_remote_callbacks remote_callbacks;
+ git_fetch_options fetch_opts;
int bare;
git_clone_local_t local;
const char* checkout_branch;
- git_signature *signature;
git_repository_create_cb repository_cb;
void *repository_cb_payload;
git_remote_create_cb remote_cb;
@@ -443,16 +486,21 @@ typedef enum {
GIT_CONFIG_HIGHEST_LEVEL = -1,
} git_config_level_t;
-typedef struct {
+typedef struct git_config_entry {
const char *name;
const char *value;
git_config_level_t level;
+ void (*free)(struct git_config_entry *entry);
+ void *payload;
} git_config_entry;
+void git_config_entry_free(git_config_entry *);
+
int git_repository_config(git_config **out, git_repository *repo);
int git_repository_config_snapshot(git_config **out, git_repository *repo);
void git_config_free(git_config *cfg);
+int git_config_get_entry(git_config_entry **out, const git_config *cfg, const char *name);
int git_config_get_string(const char **out, const git_config *cfg, const char *name);
int git_config_set_string(git_config *cfg, const char *name, const char *value);
int git_config_set_bool(git_config *cfg, const char *name, int value);
@@ -535,8 +583,10 @@ int git_repository_init_ext(
const char *repo_path,
git_repository_init_options *opts);
-int git_repository_set_head(git_repository *repo, const char *refname, const git_signature *signature, const char *log_message);
-int git_repository_set_head_detached(git_repository *repo, const git_oid *commitish, const git_signature *signature, const char *log_message);
+int git_repository_set_head(git_repository *repo, const char *refname);
+int git_repository_set_head_detached(git_repository *repo, const git_oid *commitish);
+int git_repository_ident(const char **name, const char **email, const git_repository *repo);
+int git_repository_set_ident(git_repository *repo, const char *name, const char *email);
int git_graph_ahead_behind(size_t *ahead, size_t *behind, git_repository *repo, const git_oid *local, const git_oid *upstream);
/*
@@ -557,25 +607,25 @@ const char *git_submodule_branch(git_submodule *subm);
typedef int64_t git_time_t;
typedef struct {
- git_time_t seconds;
- unsigned int nanoseconds;
+ int32_t seconds;
+ uint32_t nanoseconds;
} git_index_time;
typedef struct git_index_entry {
git_index_time ctime;
git_index_time mtime;
- unsigned int dev;
- unsigned int ino;
- unsigned int mode;
- unsigned int uid;
- unsigned int gid;
- git_off_t file_size;
+ uint32_t dev;
+ uint32_t ino;
+ uint32_t mode;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t file_size;
git_oid id;
- unsigned short flags;
- unsigned short flags_extended;
+ uint16_t flags;
+ uint16_t flags_extended;
const char *path;
} git_index_entry;
@@ -664,13 +714,16 @@ typedef enum {
typedef struct {
unsigned int version;
- git_merge_tree_flag_t flags;
+ git_merge_tree_flag_t tree_flags;
unsigned int rename_threshold;
unsigned int target_limit;
git_diff_similarity_metric *metric;
git_merge_file_favor_t file_favor;
+ unsigned int file_flags;
} git_merge_options;
+#define GIT_MERGE_OPTIONS_VERSION 1
+
typedef struct {
unsigned int automergeable;
const char *path;
diff --git a/pygit2/remote.py b/pygit2/remote.py
index 8d2416b..7ec5bd4 100644
--- a/pygit2/remote.py
+++ b/pygit2/remote.py
@@ -153,74 +153,44 @@ class Remote(object):
return maybe_string(C.git_remote_url(self._remote))
- @url.setter
- def url(self, value):
- err = C.git_remote_set_url(self._remote, to_bytes(value))
- check_error(err)
-
@property
def push_url(self):
"""Push url of the remote"""
return maybe_string(C.git_remote_pushurl(self._remote))
- @push_url.setter
- def push_url(self, value):
- err = C.git_remote_set_pushurl(self._remote, to_bytes(value))
- check_error(err)
-
def save(self):
"""Save a remote to its repository's configuration."""
err = C.git_remote_save(self._remote)
check_error(err)
- def fetch(self, signature=None, message=None):
+ def fetch(self, refspecs=None, message=None):
"""Perform a fetch against this remote. Returns a <TransferProgress>
object.
"""
- # Get the default callbacks first
- defaultcallbacks = ffi.new('git_remote_callbacks *')
- err = C.git_remote_init_callbacks(defaultcallbacks, 1)
- check_error(err)
+ fetch_opts = ffi.new('git_fetch_options *')
+ err = C.git_fetch_init_options(fetch_opts, C.GIT_FETCH_OPTIONS_VERSION)
- # Build custom callback structure
- callbacks = ffi.new('git_remote_callbacks *')
- callbacks.version = 1
- callbacks.sideband_progress = self._sideband_progress_cb
- callbacks.transfer_progress = self._transfer_progress_cb
- callbacks.update_tips = self._update_tips_cb
- callbacks.credentials = self._credentials_cb
+ fetch_opts.callbacks.sideband_progress = self._sideband_progress_cb
+ fetch_opts.callbacks.transfer_progress = self._transfer_progress_cb
+ fetch_opts.callbacks.update_tips = self._update_tips_cb
+ fetch_opts.callbacks.credentials = self._credentials_cb
# We need to make sure that this handle stays alive
self._self_handle = ffi.new_handle(self)
- callbacks.payload = self._self_handle
-
- err = C.git_remote_set_callbacks(self._remote, callbacks)
- try:
- check_error(err)
- except:
- self._self_handle = None
- raise
-
- if signature:
- ptr = signature._pointer[:]
- else:
- ptr = ffi.NULL
+ fetch_opts.callbacks.payload = self._self_handle
self._stored_exception = None
try:
- err = C.git_remote_fetch(self._remote, ffi.NULL, ptr, to_bytes(message))
- if self._stored_exception:
- raise self._stored_exception
-
- check_error(err)
+ with StrArray(refspecs) as arr:
+ err = C.git_remote_fetch(self._remote, arr, fetch_opts, to_bytes(message))
+ if self._stored_exception:
+ raise self._stored_exception
+ check_error(err)
finally:
- # Even on error, clear stored callbacks and reset to default
self._self_handle = None
- err = C.git_remote_set_callbacks(self._remote, defaultcallbacks)
- check_error(err)
return TransferProgress(C.git_remote_stats(self._remote))
@@ -245,12 +215,6 @@ class Remote(object):
return strarray_to_strings(specs)
- @fetch_refspecs.setter
- def fetch_refspecs(self, l):
- with StrArray(l) as arr:
- err = C.git_remote_set_fetch_refspecs(self._remote, arr)
- check_error(err)
-
@property
def push_refspecs(self):
"""Refspecs that will be used for pushing"""
@@ -261,64 +225,28 @@ class Remote(object):
return strarray_to_strings(specs)
- @push_refspecs.setter
- def push_refspecs(self, l):
- with StrArray(l) as arr:
- err = C.git_remote_set_push_refspecs(self._remote, arr)
- check_error(err)
-
- def add_fetch(self, refspec):
- """Add a fetch refspec (str) to the remote."""
- err = C.git_remote_add_fetch(self._remote, to_bytes(refspec))
- check_error(err)
-
- def add_push(self, refspec):
- """Add a push refspec (str) to the remote."""
- err = C.git_remote_add_push(self._remote, to_bytes(refspec))
- check_error(err)
-
- def push(self, specs, signature=None, message=None):
+ def push(self, specs):
"""Push the given refspec to the remote. Raises ``GitError`` on
protocol error or unpack failure.
:param [str] specs: push refspecs to use
- :param Signature signature: signature to use when updating the tips (optional)
- :param str message: message to use when updating the tips (optional)
"""
- # Get the default callbacks first
- defaultcallbacks = ffi.new('git_remote_callbacks *')
- err = C.git_remote_init_callbacks(defaultcallbacks, 1)
- check_error(err)
-
- if signature:
- sig_cptr = ffi.new('git_signature **')
- ffi.buffer(sig_cptr)[:] = signature._pointer[:]
- sig_ptr = sig_cptr[0]
- else:
- sig_ptr = ffi.NULL
+ push_opts = ffi.new('git_push_options *')
+ err = C.git_push_init_options(push_opts, C.GIT_PUSH_OPTIONS_VERSION)
# Build custom callback structure
- callbacks = ffi.new('git_remote_callbacks *')
- callbacks.version = 1
- callbacks.sideband_progress = self._sideband_progress_cb
- callbacks.transfer_progress = self._transfer_progress_cb
- callbacks.update_tips = self._update_tips_cb
- callbacks.credentials = self._credentials_cb
- callbacks.push_update_reference = self._push_update_reference_cb
+ push_opts.callbacks.sideband_progress = self._sideband_progress_cb
+ push_opts.callbacks.transfer_progress = self._transfer_progress_cb
+ push_opts.callbacks.update_tips = self._update_tips_cb
+ push_opts.callbacks.credentials = self._credentials_cb
+ push_opts.callbacks.push_update_reference = self._push_update_reference_cb
# We need to make sure that this handle stays alive
self._self_handle = ffi.new_handle(self)
- callbacks.payload = self._self_handle
-
- try:
- err = C.git_remote_set_callbacks(self._remote, callbacks)
- check_error(err)
- except:
- self._self_handle = None
- raise
+ push_opts.callbacks.payload = self._self_handle
try:
with StrArray(specs) as refspecs:
- err = C.git_remote_push(self._remote, refspecs, ffi.NULL, sig_ptr, to_bytes(message))
+ err = C.git_remote_push(self._remote, refspecs, ffi.NULL)
check_error(err)
finally:
self._self_handle = None
@@ -551,3 +479,29 @@ class RemoteCollection(object):
"""
err = C.git_remote_delete(self._repo._repo, to_bytes(name))
check_error(err)
+
+ def set_url(self, name, url):
+ """ Set the URL for a remote
+ """
+ err = C.git_remote_set_url(self._repo._repo, to_bytes(name), to_bytes(url))
+ check_error(err)
+
+ def set_push_url(self, name, url):
+ """Set the push-URL for a remote
+ """
+ err = C.git_remote_set_pushurl(self._repo._repo, to_bytes(name), to_bytes(url))
+ check_error(err)
+
+ def add_fetch(self, name, refspec):
+ """Add a fetch refspec (str) to the remote
+ """
+
+ err = C.git_remote_add_fetch(self._repo._repo, to_bytes(name), to_bytes(refspec))
+ check_error(err)
+
+ def add_push(self, name, refspec):
+ """Add a push refspec (str) to the remote
+ """
+
+ err = C.git_remote_add_push(self._repo._repo, to_bytes(name), to_bytes(refspec))
+ check_error(err)
diff --git a/pygit2/repository.py b/pygit2/repository.py
index 64c08f9..b92a3a2 100644
--- a/pygit2/repository.py
+++ b/pygit2/repository.py
@@ -40,7 +40,7 @@ else:
# Import from pygit2
from _pygit2 import Repository as _Repository
from _pygit2 import Oid, GIT_OID_HEXSZ, GIT_OID_MINPREFIXLEN
-from _pygit2 import GIT_CHECKOUT_SAFE_CREATE, GIT_DIFF_NORMAL
+from _pygit2 import GIT_CHECKOUT_SAFE, GIT_CHECKOUT_RECREATE_MISSING, GIT_DIFF_NORMAL
from _pygit2 import GIT_FILEMODE_LINK
from _pygit2 import Reference, Tree, Commit, Blob
@@ -190,8 +190,8 @@ class Repository(_Repository):
# References we need to keep to strings and so forth
refs = []
- # pygit2's default is SAFE_CREATE
- copts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE
+ # pygit2's default is SAFE | RECREATE_MISSING
+ copts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_RECREATE_MISSING
# and go through the arguments to see what the user wanted
if strategy:
copts.checkout_strategy = strategy
@@ -235,7 +235,7 @@ class Repository(_Repository):
Checkout the given reference using the given strategy, and update
the HEAD.
The reference may be a reference name or a Reference object.
- The default strategy is GIT_CHECKOUT_SAFE_CREATE.
+ The default strategy is GIT_CHECKOUT_SAFE | GIT_CHECKOUT_RECREATE_MISSING.
To checkout from the HEAD, just pass 'HEAD'::
@@ -251,7 +251,7 @@ class Repository(_Repository):
the current branch will be switched to this one.
:param int strategy: A ``GIT_CHECKOUT_`` value. The default is
- ``GIT_CHECKOUT_SAFE_CREATE``.
+ ``GIT_CHECKOUT_SAFE``.
:param str directory: Alternative checkout path to workdir.
@@ -281,50 +281,29 @@ class Repository(_Repository):
else:
from_ = head.target.hex
- try:
- signature = self.default_signature
- except Exception:
- signature = None
-
- reflog_text = "checkout: moving from %s to %s" % (from_, reference)
- self.set_head(refname, signature, reflog_text)
+ self.set_head(refname)
#
# Setting HEAD
#
- def set_head(self, target, signature=None, message=None):
+ def set_head(self, target):
"""Set HEAD to point to the given target
Arguments:
target
The new target for HEAD. Can be a string or Oid (to detach)
-
- signature
- Signature to use for the reflog. If not provided, the repository's
- default will be used
-
- message
- Message to use for the reflog
"""
- sig_ptr = ffi.new('git_signature **')
- if signature:
- ffi.buffer(sig_ptr)[:] = signature._pointer[:]
-
- message_ptr = ffi.NULL
- if message_ptr:
- message_ptr = to_bytes(message)
-
if isinstance(target, Oid):
oid = ffi.new('git_oid *')
ffi.buffer(oid)[:] = target.raw[:]
- err = C.git_repository_set_head_detached(self._repo, oid, sig_ptr[0], message_ptr)
+ err = C.git_repository_set_head_detached(self._repo, oid)
check_error(err)
return
# if it's a string, then it's a reference name
- err = C.git_repository_set_head(self._repo, to_bytes(target), sig_ptr[0], message_ptr)
+ err = C.git_repository_set_head(self._repo, to_bytes(target))
check_error(err)
#
@@ -802,3 +781,27 @@ class Repository(_Repository):
return ffi.string(cvalue[0]).decode('utf-8')
assert False, "the attribute value from libgit2 is invalid"
+
+ #
+ # Identity for reference operations
+ #
+ @property
+ def ident(self):
+ cname = ffi.new('char **')
+ cemail = ffi.new('char **')
+
+ err = C.git_repository_ident(cname, cemail, self._repo)
+ check_error(err)
+
+ return (ffi.string(cname).decode('utf-8'), ffi.string(cemail).decode('utf-8'))
+
+ def set_ident(self, name, email):
+ """Set the identity to be used for reference operations
+
+ Updates to some references also append data to their
+ reflog. You can use this method to set what identity will be
+ used. If none is set, it will be read from the configuration.
+ """
+
+ err = C.git_repository_set_ident(self._repo, to_bytes(name), to_bytes(email))
+ check_error(err)
diff --git a/pygit2/utils.py b/pygit2/utils.py
index 89bc7ee..5b6a365 100644
--- a/pygit2/utils.py
+++ b/pygit2/utils.py
@@ -61,6 +61,11 @@ class StrArray(object):
"""
def __init__(self, l):
+ # Allow passing in None as lg2 typically considers them the same as empty
+ if l is None:
+ self.array = ffi.NULL
+ return
+
if not isinstance(l, list):
raise TypeError("Value must be a list")
diff --git a/src/branch.c b/src/branch.c
index 1793cea..d725ab1 100644
--- a/src/branch.c
+++ b/src/branch.c
@@ -101,7 +101,7 @@ Branch_rename(Branch *self, PyObject *args)
if (!PyArg_ParseTuple(args, "s|i", &c_name, &force))
return NULL;
- err = git_branch_move(&c_out, self->reference, c_name, force, NULL, NULL);
+ err = git_branch_move(&c_out, self->reference, c_name, force);
if (err == GIT_OK)
return wrap_branch(c_out, self->repo);
else
diff --git a/src/pygit2.c b/src/pygit2.c
index eedff26..12d365f 100644
--- a/src/pygit2.c
+++ b/src/pygit2.c
@@ -273,10 +273,11 @@ moduleinit(PyObject* m)
ADD_CONSTANT_INT(m, GIT_STATUS_WT_MODIFIED)
ADD_CONSTANT_INT(m, GIT_STATUS_WT_DELETED)
ADD_CONSTANT_INT(m, GIT_STATUS_IGNORED) /* Flags for ignored files */
+ ADD_CONSTANT_INT(m, GIT_STATUS_CONFLICTED)
/* Different checkout strategies */
ADD_CONSTANT_INT(m, GIT_CHECKOUT_NONE)
ADD_CONSTANT_INT(m, GIT_CHECKOUT_SAFE)
- ADD_CONSTANT_INT(m, GIT_CHECKOUT_SAFE_CREATE)
+ ADD_CONSTANT_INT(m, GIT_CHECKOUT_RECREATE_MISSING)
ADD_CONSTANT_INT(m, GIT_CHECKOUT_FORCE)
ADD_CONSTANT_INT(m, GIT_CHECKOUT_ALLOW_CONFLICTS)
ADD_CONSTANT_INT(m, GIT_CHECKOUT_REMOVE_UNTRACKED)
diff --git a/src/reference.c b/src/reference.c
index 4d8e56e..2a20cca 100644
--- a/src/reference.c
+++ b/src/reference.c
@@ -163,7 +163,7 @@ Reference_rename(Reference *self, PyObject *py_name)
return NULL;
/* Rename */
- err = git_reference_rename(&new_reference, self->reference, c_name, 0, NULL, NULL);
+ err = git_reference_rename(&new_reference, self->reference, c_name, 0, NULL);
git_reference_free(self->reference);
free(c_name);
if (err < 0)
@@ -228,7 +228,7 @@ Reference_target__get__(Reference *self)
}
PyDoc_STRVAR(Reference_set_target__doc__,
- "set_target(target, [signature, message])\n"
+ "set_target(target, [message])\n"
"\n"
"Set the target of this reference.\n"
"\n"
@@ -240,9 +240,6 @@ PyDoc_STRVAR(Reference_set_target__doc__,
"\n"
"target\n"
" The new target for this reference\n"
- "signature\n"
- " The signature to use for the reflog. If left out, the repository's\n"
- " default identity will be used.\n"
"message\n"
" Message to use for the reflog.\n");
@@ -253,28 +250,23 @@ Reference_set_target(Reference *self, PyObject *args, PyObject *kwds)
char *c_name;
int err;
git_reference *new_ref;
- const git_signature *sig = NULL;
PyObject *py_target = NULL;
- Signature *py_signature = NULL;
const char *message = NULL;
- char *keywords[] = {"target", "signature", "message", NULL};
+ char *keywords[] = {"target", "message", NULL};
CHECK_REFERENCE(self);
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O!s", keywords,
- &py_target, &SignatureType, &py_signature, &message))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s", keywords,
+ &py_target, &message))
return NULL;
- if (py_signature)
- sig = py_signature->signature;
-
/* Case 1: Direct */
if (GIT_REF_OID == git_reference_type(self->reference)) {
err = py_oid_to_git_oid_expand(self->repo->repo, py_target, &oid);
if (err < 0)
goto error;
- err = git_reference_set_target(&new_ref, self->reference, &oid, sig, message);
+ err = git_reference_set_target(&new_ref, self->reference, &oid, message);
if (err < 0)
goto error;
@@ -288,7 +280,7 @@ Reference_set_target(Reference *self, PyObject *args, PyObject *kwds)
if (c_name == NULL)
return NULL;
- err = git_reference_symbolic_set_target(&new_ref, self->reference, c_name, sig, message);
+ err = git_reference_symbolic_set_target(&new_ref, self->reference, c_name, message);
free(c_name);
if (err < 0)
goto error;
diff --git a/src/repository.c b/src/repository.c
index de93bb3..0195c01 100644
--- a/src/repository.c
+++ b/src/repository.c
@@ -637,7 +637,7 @@ Repository_merge(Repository *self, PyObject *py_oid)
if (err < 0)
return Error_set(err);
- checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+ checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE | GIT_CHECKOUT_RECREATE_MISSING;
err = git_merge(self->repo,
(const git_annotated_commit **)&commit, 1,
&merge_opts, &checkout_opts);
@@ -677,7 +677,7 @@ Repository_cherrypick(Repository *self, PyObject *py_oid)
if (err < 0)
return Error_set(err);
- cherrypick_opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE_CREATE;
+ cherrypick_opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
err = git_cherrypick(self->repo,
commit,
(const git_cherrypick_options *)&cherrypick_opts);
@@ -989,7 +989,7 @@ Repository_create_branch(Repository *self, PyObject *args)
if (!PyArg_ParseTuple(args, "sO!|i", &c_name, &CommitType, &py_commit, &force))
return NULL;
- err = git_branch_create(&c_reference, self->repo, c_name, py_commit->commit, force, NULL, NULL);
+ err = git_branch_create(&c_reference, self->repo, c_name, py_commit->commit, force);
if (err < 0)
return Error_set(err);
@@ -1194,7 +1194,7 @@ Repository_create_reference_direct(Repository *self, PyObject *args,
if (err < 0)
return NULL;
- err = git_reference_create(&c_reference, self->repo, c_name, &oid, force, NULL, NULL);
+ err = git_reference_create(&c_reference, self->repo, c_name, &oid, force, NULL);
if (err < 0)
return Error_set(err);
@@ -1228,7 +1228,7 @@ Repository_create_reference_symbolic(Repository *self, PyObject *args,
return NULL;
err = git_reference_symbolic_create(&c_reference, self->repo, c_name,
- c_target, force, NULL, NULL);
+ c_target, force, NULL);
if (err < 0)
return Error_set(err);
@@ -1513,7 +1513,7 @@ Repository_reset(Repository *self, PyObject* args)
err = git_object_lookup_prefix(&target, self->repo, &oid, len,
GIT_OBJ_ANY);
- err = err < 0 ? err : git_reset(self->repo, target, reset_type, NULL, NULL, NULL);
+ err = err < 0 ? err : git_reset(self->repo, target, reset_type, NULL);
git_object_free(target);
if (err < 0)
return Error_set_oid(err, &oid, len);
diff --git a/src/types.h b/src/types.h
index f82ad47..f3c1858 100644
--- a/src/types.h
+++ b/src/types.h
@@ -32,8 +32,8 @@
#include <Python.h>
#include <git2.h>
-#if !(LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR == 22)
-#error You need a compatible libgit2 version (v0.22.x)
+#if !(LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR == 23)
+#error You need a compatible libgit2 version (v0.23.x)
#endif
/*
diff --git a/test/test_merge.py b/test/test_merge.py
index 7719d6d..86d1eea 100644
--- a/test/test_merge.py
+++ b/test/test_merge.py
@@ -82,7 +82,7 @@ class MergeTestBasic(utils.RepoTestCaseForMerging):
self.repo.merge(branch_id)
self.assertTrue(self.repo.index.conflicts is not None)
- status = pygit2.GIT_STATUS_WT_NEW | pygit2.GIT_STATUS_INDEX_DELETED
+ status = pygit2.GIT_STATUS_CONFLICTED
# Asking twice to assure the reference counting is correct
self.assertEqual({'.gitignore': status}, self.repo.status())
self.assertEqual({'.gitignore': status}, self.repo.status())
diff --git a/test/test_refs.py b/test/test_refs.py
index 1e78eb5..0d362c7 100644
--- a/test/test_refs.py
+++ b/test/test_refs.py
@@ -114,8 +114,9 @@ class ReferencesTest(utils.RepoTestCase):
reference = self.repo.lookup_reference('HEAD')
self.assertEqual(reference.target, 'refs/heads/master')
sig = Signature('foo', 'bar')
+ self.repo.set_ident('foo', 'bar')
msg = 'Hello log'
- reference.set_target('refs/heads/i18n', signature=sig, message=msg)
+ reference.set_target('refs/heads/i18n', message=msg)
self.assertEqual(reference.target, 'refs/heads/i18n')
self.assertEqual(list(reference.log())[0].message, msg)
self.assertEqualSignature(list(reference.log())[0].committer, sig)
diff --git a/test/test_remote.py b/test/test_remote.py
index 751cddc..c2e4f8f 100644
--- a/test/test_remote.py
+++ b/test/test_remote.py
@@ -100,22 +100,23 @@ class RepositoryTest(utils.RepoTestCase):
def test_remote_set_url(self):
- remote = self.repo.remotes[0]
-
+ remote = self.repo.remotes["origin"]
self.assertEqual(REMOTE_URL, remote.url)
+
new_url = 'git://github.com/cholin/pygit2.git'
- remote.url = new_url
+ self.repo.remotes.set_url("origin", new_url)
+ remote = self.repo.remotes["origin"]
self.assertEqual(new_url, remote.url)
- self.assertRaisesAssign(ValueError, remote, 'url', '')
+ self.assertRaises(ValueError, self.repo.remotes.set_url, "origin", "")
- remote.push_url = new_url
+ self.repo.remotes.set_push_url("origin", new_url)
+ remote = self.repo.remotes["origin"]
self.assertEqual(new_url, remote.push_url)
- self.assertRaisesAssign(ValueError, remote, 'push_url', '')
-
+ self.assertRaises(ValueError, self.repo.remotes.set_push_url, "origin", "")
def test_refspec(self):
- remote = self.repo.remotes[0]
+ remote = self.repo.remotes["origin"]
self.assertEqual(remote.refspec_count, 1)
refspec = remote.get_refspec(0)
@@ -140,34 +141,20 @@ class RepositoryTest(utils.RepoTestCase):
self.assertEqual(list, type(push_specs))
self.assertEqual(0, len(push_specs))
- remote.fetch_refspecs = ['+refs/*:refs/remotes/*']
- self.assertEqual('+refs/*:refs/remotes/*', remote.fetch_refspecs[0])
+ self.repo.remotes.add_fetch("origin", '+refs/test/*:refs/test/remotes/*')
+ remote = self.repo.remotes["origin"]
fetch_specs = remote.fetch_refspecs
self.assertEqual(list, type(fetch_specs))
- self.assertEqual(1, len(fetch_specs))
- self.assertEqual('+refs/*:refs/remotes/*', fetch_specs[0])
-
- remote.fetch_refspecs = ['+refs/*:refs/remotes/*',
- '+refs/test/*:refs/test/remotes/*']
- self.assertEqual('+refs/*:refs/remotes/*', remote.fetch_refspecs[0])
- self.assertEqual('+refs/test/*:refs/test/remotes/*',
- remote.fetch_refspecs[1])
+ self.assertEqual(2, len(fetch_specs))
+ self.assertEqual(['+refs/heads/*:refs/remotes/origin/*', '+refs/test/*:refs/test/remotes/*'], fetch_specs)
- remote.push_refspecs = ['+refs/*:refs/remotes/*',
- '+refs/test/*:refs/test/remotes/*']
+ self.repo.remotes.add_push("origin", '+refs/test/*:refs/test/remotes/*')
- self.assertRaises(TypeError, setattr, remote, 'push_refspecs',
- '+refs/*:refs/*')
- self.assertRaises(TypeError, setattr, remote, 'fetch_refspecs',
- '+refs/*:refs/*')
- self.assertRaises(TypeError, setattr, remote, 'fetch_refspecs',
- ['+refs/*:refs/*', 5])
-
- self.assertEqual('+refs/*:refs/remotes/*', remote.push_refspecs[0])
- self.assertEqual('+refs/test/*:refs/test/remotes/*',
- remote.push_refspecs[1])
+ self.assertRaises(TypeError, self.repo.remotes.add_fetch, ['+refs/*:refs/*', 5])
+ remote = self.repo.remotes["origin"]
+ self.assertEqual(['+refs/test/*:refs/test/remotes/*'], remote.push_refspecs)
def test_remote_list(self):
self.assertEqual(1, len(self.repo.remotes))
@@ -193,15 +180,6 @@ class RepositoryTest(utils.RepoTestCase):
remote = self.repo.remotes.create(name, url)
self.assertTrue(remote.name in [x.name for x in self.repo.remotes])
-
- def test_remote_save(self):
- remote = self.repo.remotes[0]
- remote.url = 'http://example.com/test.git'
- remote.save()
-
- self.assertEqual('http://example.com/test.git',
- self.repo.remotes[0].url)
-
@unittest.skipIf(__pypy__ is not None, "skip refcounts checks in pypy")
def test_remote_refcount(self):
start = sys.getrefcount(self.repo)
@@ -210,15 +188,6 @@ class RepositoryTest(utils.RepoTestCase):
end = sys.getrefcount(self.repo)
self.assertEqual(start, end)
- def test_add_refspec(self):
- remote = self.repo.create_remote('test_add_refspec', REMOTE_URL)
- remote.add_push('refs/heads/*:refs/heads/test_refspec/*')
- self.assertEqual('refs/heads/*:refs/heads/test_refspec/*',
- remote.push_refspecs[0])
- remote.add_fetch('+refs/heads/*:refs/remotes/test_refspec/*')
- self.assertEqual('+refs/heads/*:refs/remotes/test_refspec/*',
- remote.fetch_refspecs[1])
-
def test_remote_callback_typecheck(self):
remote = self.repo.remotes[0]
remote.progress = 5
--
2.5.0