summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt8
-rw-r--r--include/git2/checkout.h2
-rw-r--r--include/git2/config.h22
-rw-r--r--include/git2/transport.h55
-rw-r--r--src/config_file.c5
-rw-r--r--src/pack-objects.c2
-rw-r--r--src/submodule.c31
-rw-r--r--src/transports/http.c5
-rw-r--r--src/transports/smart.h6
-rw-r--r--src/transports/smart_pkt.c218
-rw-r--r--src/transports/smart_protocol.c10
-rw-r--r--tests/config/include.c42
-rw-r--r--tests/core/vector.c4
-rw-r--r--tests/submodule/inject_option.c80
-rw-r--r--tests/transports/smart/packet.c340
15 files changed, 684 insertions, 146 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c3f3e4081..7165cca6a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,12 +14,15 @@
PROJECT(libgit2 C)
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.11)
CMAKE_POLICY(SET CMP0015 NEW)
-IF (POLICY CMP0051)
+IF(POLICY CMP0051)
CMAKE_POLICY(SET CMP0051 NEW)
ENDIF()
-IF (POLICY CMP0042)
+IF(POLICY CMP0042)
CMAKE_POLICY(SET CMP0042 NEW)
ENDIF()
+IF(POLICY CMP0054)
+ CMAKE_POLICY(SET CMP0054 NEW)
+ENDIF()
# Add find modules to the path
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${libgit2_SOURCE_DIR}/cmake/Modules/")
@@ -230,6 +233,7 @@ ELSE ()
DISABLE_WARNINGS(unused-function)
ENABLE_WARNINGS(format)
ENABLE_WARNINGS(format-security)
+ ENABLE_WARNINGS(int-conversion)
IF (APPLE) # Apple deprecated OpenSSL
DISABLE_WARNINGS(deprecated-declarations)
diff --git a/include/git2/checkout.h b/include/git2/checkout.h
index 7ba0df871..485bae63f 100644
--- a/include/git2/checkout.h
+++ b/include/git2/checkout.h
@@ -67,7 +67,7 @@ GIT_BEGIN_DECL
* To emulate `git checkout -f`, use `GIT_CHECKOUT_FORCE`.
*
*
- * There are some additional flags to modified the behavior of checkout:
+ * There are some additional flags to modify the behavior of checkout:
*
* - GIT_CHECKOUT_ALLOW_CONFLICTS makes SAFE mode apply safe file updates
* even if there are conflicts (instead of cancelling the checkout).
diff --git a/include/git2/config.h b/include/git2/config.h
index 7bcca7da2..f32f7af7f 100644
--- a/include/git2/config.h
+++ b/include/git2/config.h
@@ -75,7 +75,17 @@ typedef struct git_config_entry {
*/
GIT_EXTERN(void) git_config_entry_free(git_config_entry *);
-typedef int (*git_config_foreach_cb)(const git_config_entry *, void *);
+/**
+ * A config enumeration callback
+ *
+ * @param entry the entry currently being enumerated
+ * @param payload a user-specified pointer
+ */
+typedef int (*git_config_foreach_cb)(const git_config_entry *entry, void *payload);
+
+/**
+ * An opaque structure for a configuration iterator
+ */
typedef struct git_config_iterator git_config_iterator;
/**
@@ -252,7 +262,7 @@ GIT_EXTERN(int) git_config_open_level(
* Open the global/XDG configuration file according to git's rules
*
* Git allows you to store your global configuration at
- * `$HOME/.config` or `$XDG_CONFIG_HOME/git/config`. For backwards
+ * `$HOME/.gitconfig` or `$XDG_CONFIG_HOME/git/config`. For backwards
* compatability, the XDG file shouldn't be used unless the use has
* created it explicitly. With this function you'll open the correct
* one to write to.
@@ -581,7 +591,7 @@ GIT_EXTERN(int) git_config_iterator_glob_new(git_config_iterator **out, const gi
/**
* Perform an operation on each config variable matching a regular expression.
*
- * This behaviors like `git_config_foreach` with an additional filter of a
+ * This behaves like `git_config_foreach` with an additional filter of a
* regular expression that filters which config keys are passed to the
* callback.
*
@@ -711,11 +721,11 @@ GIT_EXTERN(int) git_config_parse_int64(int64_t *out, const char *value);
GIT_EXTERN(int) git_config_parse_path(git_buf *out, const char *value);
/**
- * Perform an operation on each config variable in given config backend
+ * Perform an operation on each config variable in a given config backend,
* matching a regular expression.
*
- * This behaviors like `git_config_foreach_match` except instead of all config
- * entries it just enumerates through the given backend entry.
+ * This behaves like `git_config_foreach_match` except that only config
+ * entries from the given backend entry are enumerated.
*
* The regular expression is applied case-sensitively on the normalized form of
* the variable name: the section and variable parts are lower-cased. The
diff --git a/include/git2/transport.h b/include/git2/transport.h
index 0c371bf4b..92642514e 100644
--- a/include/git2/transport.h
+++ b/include/git2/transport.h
@@ -77,44 +77,73 @@ typedef struct {
*** Begin interface for credentials acquisition ***
*/
-/** Authentication type requested */
+/**
+ * Supported credential types
+ *
+ * This represents the various types of authentication methods supported by
+ * the library.
+ */
typedef enum {
- /* git_cred_userpass_plaintext */
+ /**
+ * A vanilla user/password request
+ * @see git_cred_userpass_plaintext_new
+ */
GIT_CREDTYPE_USERPASS_PLAINTEXT = (1u << 0),
- /* git_cred_ssh_key */
+ /**
+ * An SSH key-based authentication request
+ * @see git_cred_ssh_key_new
+ */
GIT_CREDTYPE_SSH_KEY = (1u << 1),
- /* git_cred_ssh_custom */
+ /**
+ * An SSH key-based authentication request, with a custom signature
+ * @see git_cred_ssh_custom_new
+ */
GIT_CREDTYPE_SSH_CUSTOM = (1u << 2),
- /* git_cred_default */
+ /**
+ * An NTLM/Negotiate-based authentication request.
+ * @see git_cred_default
+ */
GIT_CREDTYPE_DEFAULT = (1u << 3),
- /* git_cred_ssh_interactive */
+ /**
+ * An SSH interactive authentication request
+ * @see git_cred_ssh_interactive_new
+ */
GIT_CREDTYPE_SSH_INTERACTIVE = (1u << 4),
/**
- * Username-only information
+ * Username-only authentication request
*
- * If the SSH transport does not know which username to use,
- * it will ask via this credential type.
+ * Used as a pre-authentication step if the underlying transport
+ * (eg. SSH, with no username in its URL) does not know which username
+ * to use.
+ *
+ * @see git_cred_username_new
*/
GIT_CREDTYPE_USERNAME = (1u << 5),
/**
- * Credentials read from memory.
+ * An SSH key-based authentication request
+ *
+ * Allows credentials to be read from memory instead of files.
+ * Note that because of differences in crypto backend support, it might
+ * not be functional.
*
- * Only available for libssh2+OpenSSL for now.
+ * @see git_cred_ssh_key_memory_new
*/
GIT_CREDTYPE_SSH_MEMORY = (1u << 6),
} git_credtype_t;
-/* The base structure for all credential types */
typedef struct git_cred git_cred;
+/**
+ * The base structure for all credential types
+ */
struct git_cred {
- git_credtype_t credtype;
+ git_credtype_t credtype; /**< A type of credential */
void (*free)(git_cred *cred);
};
diff --git a/src/config_file.c b/src/config_file.c
index e8740d35f..57db97d8b 100644
--- a/src/config_file.c
+++ b/src/config_file.c
@@ -664,6 +664,9 @@ static int parse_include(git_config_parser *reader,
char *dir;
int result;
+ if (!file)
+ return 0;
+
if ((result = git_path_dirname_r(&path, reader->file->path)) < 0)
return result;
@@ -765,7 +768,7 @@ static int parse_conditional_include(git_config_parser *reader,
size_t i;
int error = 0, matches;
- if (!parse_data->repo)
+ if (!parse_data->repo || !file)
return 0;
condition = git__substrdup(section + strlen("includeIf."),
diff --git a/src/pack-objects.c b/src/pack-objects.c
index 2b786df33..58eaac616 100644
--- a/src/pack-objects.c
+++ b/src/pack-objects.c
@@ -1676,7 +1676,7 @@ int insert_tree(git_packbuilder *pb, git_tree *tree)
break;
case GIT_OBJ_BLOB:
- if ((error = retrieve_object(&obj, pb, git_tree_id(tree))) < 0)
+ if ((error = retrieve_object(&obj, pb, entry_id)) < 0)
return error;
if (obj->uninteresting)
continue;
diff --git a/src/submodule.c b/src/submodule.c
index 9231f08b1..825e85a52 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -1865,6 +1865,14 @@ static int get_value(const char **out, git_config *cfg, git_buf *buf, const char
return error;
}
+static bool looks_like_command_line_option(const char *s)
+{
+ if (s && s[0] == '-')
+ return true;
+
+ return false;
+}
+
static int submodule_read_config(git_submodule *sm, git_config *cfg)
{
git_buf key = GIT_BUF_INIT;
@@ -1878,24 +1886,31 @@ static int submodule_read_config(git_submodule *sm, git_config *cfg)
if ((error = get_value(&value, cfg, &key, sm->name, "path")) == 0) {
in_config = 1;
+ /* We would warn here if we had that API */
+ if (!looks_like_command_line_option(value)) {
/*
* TODO: if case insensitive filesystem, then the following strcmp
* should be strcasecmp
*/
- if (strcmp(sm->name, value) != 0) {
- if (sm->path != sm->name)
- git__free(sm->path);
- sm->path = git__strdup(value);
- GITERR_CHECK_ALLOC(sm->path);
+ if (strcmp(sm->name, value) != 0) {
+ if (sm->path != sm->name)
+ git__free(sm->path);
+ sm->path = git__strdup(value);
+ GITERR_CHECK_ALLOC(sm->path);
+ }
+
}
} else if (error != GIT_ENOTFOUND) {
goto cleanup;
}
if ((error = get_value(&value, cfg, &key, sm->name, "url")) == 0) {
- in_config = 1;
- sm->url = git__strdup(value);
- GITERR_CHECK_ALLOC(sm->url);
+ /* We would warn here if we had that API */
+ if (!looks_like_command_line_option(value)) {
+ in_config = 1;
+ sm->url = git__strdup(value);
+ GITERR_CHECK_ALLOC(sm->url);
+ }
} else if (error != GIT_ENOTFOUND) {
goto cleanup;
}
diff --git a/src/transports/http.c b/src/transports/http.c
index bc3ab18e2..df0d342b9 100644
--- a/src/transports/http.c
+++ b/src/transports/http.c
@@ -142,7 +142,7 @@ static int auth_context_match(
}
if (!scheme)
- return -1;
+ return 0;
/* See if authentication has already started for this scheme */
git_vector_foreach(&t->auth_contexts, i, c) {
@@ -188,6 +188,9 @@ static int apply_credentials(git_buf *buf, http_subtransport *t)
if (auth_context_match(&context, t, credtype_match, &cred->credtype) < 0)
return -1;
+ if (!context)
+ return 0;
+
return context->next_token(buf, context, cred);
}
diff --git a/src/transports/smart.h b/src/transports/smart.h
index 057d7e6e0..abf80286b 100644
--- a/src/transports/smart.h
+++ b/src/transports/smart.h
@@ -90,7 +90,7 @@ typedef struct {
typedef struct {
git_pkt_type type;
- int len;
+ size_t len;
char data[GIT_FLEX_ARRAY];
} git_pkt_data;
@@ -98,7 +98,7 @@ typedef git_pkt_data git_pkt_progress;
typedef struct {
git_pkt_type type;
- int len;
+ size_t len;
char error[GIT_FLEX_ARRAY];
} git_pkt_err;
@@ -188,7 +188,7 @@ int git_smart__get_push_stream(transport_smart *t, git_smart_subtransport_stream
int git_smart__update_heads(transport_smart *t, git_vector *symrefs);
/* smart_pkt.c */
-int git_pkt_parse_line(git_pkt **head, const char *line, const char **out, size_t len);
+int git_pkt_parse_line(git_pkt **head, const char **endptr, const char *line, size_t linelen);
int git_pkt_buffer_flush(git_buf *buf);
int git_pkt_send_flush(GIT_SOCKET s);
int git_pkt_buffer_done(git_buf *buf);
diff --git a/src/transports/smart_pkt.c b/src/transports/smart_pkt.c
index 00798c396..6a404efe4 100644
--- a/src/transports/smart_pkt.c
+++ b/src/transports/smart_pkt.c
@@ -43,34 +43,43 @@ static int flush_pkt(git_pkt **out)
static int ack_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_ack *pkt;
- GIT_UNUSED(line);
- GIT_UNUSED(len);
pkt = git__calloc(1, sizeof(git_pkt_ack));
GITERR_CHECK_ALLOC(pkt);
-
pkt->type = GIT_PKT_ACK;
- line += 3;
- len -= 3;
- if (len >= GIT_OID_HEXSZ) {
- git_oid_fromstr(&pkt->oid, line + 1);
- line += GIT_OID_HEXSZ + 1;
- len -= GIT_OID_HEXSZ + 1;
- }
+ if (git__prefixncmp(line, len, "ACK "))
+ goto out_err;
+ line += 4;
+ len -= 4;
+
+ if (len < GIT_OID_HEXSZ || git_oid_fromstr(&pkt->oid, line) < 0)
+ goto out_err;
+ line += GIT_OID_HEXSZ;
+ len -= GIT_OID_HEXSZ;
+
+ if (len && line[0] == ' ') {
+ line++;
+ len--;
- if (len >= 7) {
- if (!git__prefixcmp(line + 1, "continue"))
+ if (!git__prefixncmp(line, len, "continue"))
pkt->status = GIT_ACK_CONTINUE;
- if (!git__prefixcmp(line + 1, "common"))
+ else if (!git__prefixncmp(line, len, "common"))
pkt->status = GIT_ACK_COMMON;
- if (!git__prefixcmp(line + 1, "ready"))
+ else if (!git__prefixncmp(line, len, "ready"))
pkt->status = GIT_ACK_READY;
+ else
+ goto out_err;
}
*out = (git_pkt *) pkt;
return 0;
+
+out_err:
+ giterr_set(GITERR_NET, "error parsing ACK pkt-line");
+ git__free(pkt);
+ return -1;
}
static int nak_pkt(git_pkt **out)
@@ -107,10 +116,12 @@ static int comment_pkt(git_pkt **out, const char *line, size_t len)
static int err_pkt(git_pkt **out, const char *line, size_t len)
{
- git_pkt_err *pkt;
+ git_pkt_err *pkt = NULL;
size_t alloclen;
/* Remove "ERR " from the line */
+ if (git__prefixncmp(line, len, "ERR "))
+ goto out_err;
line += 4;
len -= 4;
@@ -118,15 +129,20 @@ static int err_pkt(git_pkt **out, const char *line, size_t len)
GITERR_CHECK_ALLOC_ADD(&alloclen, alloclen, 1);
pkt = git__malloc(alloclen);
GITERR_CHECK_ALLOC(pkt);
-
pkt->type = GIT_PKT_ERR;
- pkt->len = (int)len;
+ pkt->len = len;
+
memcpy(pkt->error, line, len);
pkt->error[len] = '\0';
*out = (git_pkt *) pkt;
return 0;
+
+out_err:
+ giterr_set(GITERR_NET, "error parsing ERR pkt-line");
+ git__free(pkt);
+ return -1;
}
static int data_pkt(git_pkt **out, const char *line, size_t len)
@@ -142,7 +158,7 @@ static int data_pkt(git_pkt **out, const char *line, size_t len)
GITERR_CHECK_ALLOC(pkt);
pkt->type = GIT_PKT_DATA;
- pkt->len = (int) len;
+ pkt->len = len;
memcpy(pkt->data, line, len);
*out = (git_pkt *) pkt;
@@ -163,7 +179,7 @@ static int sideband_progress_pkt(git_pkt **out, const char *line, size_t len)
GITERR_CHECK_ALLOC(pkt);
pkt->type = GIT_PKT_PROGRESS;
- pkt->len = (int) len;
+ pkt->len = len;
memcpy(pkt->data, line, len);
*out = (git_pkt *) pkt;
@@ -199,33 +215,25 @@ static int sideband_error_pkt(git_pkt **out, const char *line, size_t len)
*/
static int ref_pkt(git_pkt **out, const char *line, size_t len)
{
- int error;
git_pkt_ref *pkt;
size_t alloclen;
- if (len < GIT_OID_HEXSZ + 1) {
- giterr_set(GITERR_NET, "error parsing pkt-line");
- return -1;
- }
-
- pkt = git__malloc(sizeof(git_pkt_ref));
+ pkt = git__calloc(1, sizeof(git_pkt_ref));
GITERR_CHECK_ALLOC(pkt);
-
- memset(pkt, 0x0, sizeof(git_pkt_ref));
pkt->type = GIT_PKT_REF;
- if ((error = git_oid_fromstr(&pkt->head.oid, line)) < 0)
- goto error_out;
-
- /* Check for a bit of consistency */
- if (line[GIT_OID_HEXSZ] != ' ') {
- giterr_set(GITERR_NET, "error parsing pkt-line");
- error = -1;
- goto error_out;
- }
- /* Jump from the name */
- line += GIT_OID_HEXSZ + 1;
- len -= (GIT_OID_HEXSZ + 1);
+ if (len < GIT_OID_HEXSZ || git_oid_fromstr(&pkt->head.oid, line) < 0)
+ goto out_err;
+ line += GIT_OID_HEXSZ;
+ len -= GIT_OID_HEXSZ;
+
+ if (git__prefixncmp(line, len, " "))
+ goto out_err;
+ line++;
+ len--;
+
+ if (!len)
+ goto out_err;
if (line[len - 1] == '\n')
--len;
@@ -237,36 +245,36 @@ static int ref_pkt(git_pkt **out, const char *line, size_t len)
memcpy(pkt->head.name, line, len);
pkt->head.name[len] = '\0';
- if (strlen(pkt->head.name) < len) {
+ if (strlen(pkt->head.name) < len)
pkt->capabilities = strchr(pkt->head.name, '\0') + 1;
- }
*out = (git_pkt *)pkt;
return 0;
-error_out:
+out_err:
+ giterr_set(GITERR_NET, "error parsing REF pkt-line");
+ if (pkt)
+ git__free(pkt->head.name);
git__free(pkt);
- return error;
+ return -1;
}
static int ok_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_ok *pkt;
- const char *ptr;
size_t alloc_len;
pkt = git__malloc(sizeof(*pkt));
GITERR_CHECK_ALLOC(pkt);
-
pkt->type = GIT_PKT_OK;
- line += 3; /* skip "ok " */
- if (!(ptr = strchr(line, '\n'))) {
- giterr_set(GITERR_NET, "invalid packet line");
- git__free(pkt);
- return -1;
- }
- len = ptr - line;
+ if (git__prefixncmp(line, len, "ok "))
+ goto out_err;
+ line += 3;
+ len -= 3;
+
+ if (line[len - 1] == '\n')
+ --len;
GITERR_CHECK_ALLOC_ADD(&alloc_len, len, 1);
pkt->ref = git__malloc(alloc_len);
@@ -277,6 +285,11 @@ static int ok_pkt(git_pkt **out, const char *line, size_t len)
*out = (git_pkt *)pkt;
return 0;
+
+out_err:
+ giterr_set(GITERR_NET, "error parsing OK pkt-line");
+ git__free(pkt);
+ return -1;
}
static int ng_pkt(git_pkt **out, const char *line, size_t len)
@@ -293,9 +306,9 @@ static int ng_pkt(git_pkt **out, const char *line, size_t len)
eol = line + len;
- if (len < 3)
+ if (git__prefixncmp(line, len, "ng "))
goto out_err;
- line += 3; /* skip "ng " */
+ line += 3;
if (!(ptr = memchr(line, ' ', eol - line)))
goto out_err;
@@ -337,13 +350,11 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len)
{
git_pkt_unpack *pkt;
- GIT_UNUSED(len);
-
pkt = git__malloc(sizeof(*pkt));
GITERR_CHECK_ALLOC(pkt);
-
pkt->type = GIT_PKT_UNPACK;
- if (!git__prefixcmp(line, "unpack ok"))
+
+ if (!git__prefixncmp(line, len, "unpack ok"))
pkt->unpack_ok = 1;
else
pkt->unpack_ok = 0;
@@ -352,13 +363,17 @@ static int unpack_pkt(git_pkt **out, const char *line, size_t len)
return 0;
}
-static int32_t parse_len(const char *line)
+static int parse_len(size_t *out, const char *line, size_t linelen)
{
char num[PKT_LEN_SIZE + 1];
int i, k, error;
int32_t len;
const char *num_end;
+ /* Not even enough for the length */
+ if (linelen < PKT_LEN_SIZE)
+ return GIT_EBUFS;
+
memcpy(num, line, PKT_LEN_SIZE);
num[PKT_LEN_SIZE] = '\0';
@@ -379,7 +394,11 @@ static int32_t parse_len(const char *line)
if ((error = git__strtol32(&len, num, &num_end, 16)) < 0)
return error;
- return len;
+ if (len < 0)
+ return -1;
+
+ *out = (size_t) len;
+ return 0;
}
/*
@@ -396,35 +415,32 @@ static int32_t parse_len(const char *line)
*/
int git_pkt_parse_line(
- git_pkt **head, const char *line, const char **out, size_t bufflen)
+ git_pkt **pkt, const char **endptr, const char *line, size_t linelen)
{
- int ret;
- int32_t len;
-
- /* Not even enough for the length */
- if (bufflen > 0 && bufflen < PKT_LEN_SIZE)
- return GIT_EBUFS;
+ int error;
+ size_t len;
- len = parse_len(line);
- if (len < 0) {
+ if ((error = parse_len(&len, line, linelen)) < 0) {
/*
- * If we fail to parse the length, it might be because the
- * server is trying to send us the packfile already.
+ * If we fail to parse the length, it might be
+ * because the server is trying to send us the
+ * packfile already or because we do not yet have
+ * enough data.
*/
- if (bufflen >= 4 && !git__prefixcmp(line, "PACK")) {
+ if (error == GIT_EBUFS)
+ ;
+ else if (!git__prefixncmp(line, linelen, "PACK"))
giterr_set(GITERR_NET, "unexpected pack file");
- } else {
+ else
giterr_set(GITERR_NET, "bad packet length");
- }
-
- return -1;
+ return error;
}
/*
- * If we were given a buffer length, then make sure there is
- * enough in the buffer to satisfy this line
+ * Make sure there is enough in the buffer to satisfy
+ * this line.
*/
- if (bufflen > 0 && bufflen < (size_t)len)
+ if (linelen < len)
return GIT_EBUFS;
/*
@@ -447,38 +463,38 @@ int git_pkt_parse_line(
}
if (len == 0) { /* Flush pkt */
- *out = line;
- return flush_pkt(head);
+ *endptr = line;
+ return flush_pkt(pkt);
}
len -= PKT_LEN_SIZE; /* the encoded length includes its own size */
if (*line == GIT_SIDE_BAND_DATA)
- ret = data_pkt(head, line, len);
+ error = data_pkt(pkt, line, len);
else if (*line == GIT_SIDE_BAND_PROGRESS)
- ret = sideband_progress_pkt(head, line, len);
+ error = sideband_progress_pkt(pkt, line, len);
else if (*line == GIT_SIDE_BAND_ERROR)
- ret = sideband_error_pkt(head, line, len);
- else if (!git__prefixcmp(line, "ACK"))
- ret = ack_pkt(head, line, len);
- else if (!git__prefixcmp(line, "NAK"))
- ret = nak_pkt(head);
- else if (!git__prefixcmp(line, "ERR "))
- ret = err_pkt(head, line, len);
+ error = sideband_error_pkt(pkt, line, len);
+ else if (!git__prefixncmp(line, len, "ACK"))
+ error = ack_pkt(pkt, line, len);
+ else if (!git__prefixncmp(line, len, "NAK"))
+ error = nak_pkt(pkt);
+ else if (!git__prefixncmp(line, len, "ERR"))
+ error = err_pkt(pkt, line, len);
else if (*line == '#')
- ret = comment_pkt(head, line, len);
- else if (!git__prefixcmp(line, "ok"))
- ret = ok_pkt(head, line, len);
- else if (!git__prefixcmp(line, "ng"))
- ret = ng_pkt(head, line, len);
- else if (!git__prefixcmp(line, "unpack"))
- ret = unpack_pkt(head, line, len);
+ error = comment_pkt(pkt, line, len);
+ else if (!git__prefixncmp(line, len, "ok"))
+ error = ok_pkt(pkt, line, len);
+ else if (!git__prefixncmp(line, len, "ng"))
+ error = ng_pkt(pkt, line, len);
+ else if (!git__prefixncmp(line, len, "unpack"))
+ error = unpack_pkt(pkt, line, len);
else
- ret = ref_pkt(head, line, len);
+ error = ref_pkt(pkt, line, len);
- *out = line + len;
+ *endptr = line + len;
- return ret;
+ return error;
}
void git_pkt_free(git_pkt *pkt)
diff --git a/src/transports/smart_protocol.c b/src/transports/smart_protocol.c
index ce63cb195..10a5b4e2e 100644
--- a/src/transports/smart_protocol.c
+++ b/src/transports/smart_protocol.c
@@ -44,7 +44,7 @@ int git_smart__store_refs(transport_smart *t, int flushes)
do {
if (buf->offset > 0)
- error = git_pkt_parse_line(&pkt, buf->data, &line_end, buf->offset);
+ error = git_pkt_parse_line(&pkt, &line_end, buf->data, buf->offset);
else
error = GIT_EBUFS;
@@ -217,7 +217,7 @@ static int recv_pkt(git_pkt **out_pkt, git_pkt_type *out_type, gitno_buffer *buf
do {
if (buf->offset > 0)
- error = git_pkt_parse_line(&pkt, ptr, &line_end, buf->offset);
+ error = git_pkt_parse_line(&pkt, &line_end, ptr, buf->offset);
else
error = GIT_EBUFS;
@@ -755,7 +755,7 @@ static int add_push_report_sideband_pkt(git_push *push, git_pkt_data *data_pkt,
}
while (line_len > 0) {
- error = git_pkt_parse_line(&pkt, line, &line_end, line_len);
+ error = git_pkt_parse_line(&pkt, &line_end, line, line_len);
if (error == GIT_EBUFS) {
/* Buffer the data when the inner packet is split
@@ -798,8 +798,8 @@ static int parse_report(transport_smart *transport, git_push *push)
for (;;) {
if (buf->offset > 0)
- error = git_pkt_parse_line(&pkt, buf->data,
- &line_end, buf->offset);
+ error = git_pkt_parse_line(&pkt, &line_end,
+ buf->data, buf->offset);
else
error = GIT_EBUFS;
diff --git a/tests/config/include.c b/tests/config/include.c
index d2ea2c2fd..bab59bcbe 100644
--- a/tests/config/include.c
+++ b/tests/config/include.c
@@ -35,6 +35,8 @@ void test_config_include__absolute(void)
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz"));
cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
+
+ cl_git_pass(p_unlink("config-include-absolute"));
}
void test_config_include__homedir(void)
@@ -48,6 +50,8 @@ void test_config_include__homedir(void)
cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
cl_sandbox_set_search_path_defaults();
+
+ cl_git_pass(p_unlink("config-include-homedir"));
}
/* We need to pretend that the variables were defined where the file was included */
@@ -66,6 +70,9 @@ void test_config_include__ordering(void)
git_buf_clear(&buf);
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar.baz"));
cl_assert_equal_s("huzzah", git_buf_cstr(&buf));
+
+ cl_git_pass(p_unlink("included"));
+ cl_git_pass(p_unlink("including"));
}
/* We need to pretend that the variables were defined where the file was included */
@@ -76,8 +83,18 @@ void test_config_include__depth(void)
cl_git_fail(git_config_open_ondisk(&cfg, "a"));
- p_unlink("a");
- p_unlink("b");
+ cl_git_pass(p_unlink("a"));
+ cl_git_pass(p_unlink("b"));
+}
+
+void test_config_include__empty_path_sanely_handled(void)
+{
+ cl_git_mkfile("a", "[include]\npath");
+ cl_git_pass(git_config_open_ondisk(&cfg, "a"));
+ cl_git_pass(git_config_get_string_buf(&buf, cfg, "include.path"));
+ cl_assert_equal_s("", git_buf_cstr(&buf));
+
+ cl_git_pass(p_unlink("a"));
}
void test_config_include__missing(void)
@@ -89,6 +106,8 @@ void test_config_include__missing(void)
cl_assert(giterr_last() == NULL);
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar"));
cl_assert_equal_s("baz", git_buf_cstr(&buf));
+
+ cl_git_pass(p_unlink("including"));
}
void test_config_include__missing_homedir(void)
@@ -103,6 +122,7 @@ void test_config_include__missing_homedir(void)
cl_assert_equal_s("baz", git_buf_cstr(&buf));
cl_sandbox_set_search_path_defaults();
+ cl_git_pass(p_unlink("including"));
}
#define replicate10(s) s s s s s s s s s s
@@ -122,6 +142,10 @@ void test_config_include__depth2(void)
git_buf_clear(&buf);
cl_git_pass(git_config_get_string_buf(&buf, cfg, "foo.bar2"));
cl_assert_equal_s("baz2", git_buf_cstr(&buf));
+
+ cl_git_pass(p_unlink("top-level"));
+ cl_git_pass(p_unlink("middle"));
+ cl_git_pass(p_unlink("bottom"));
}
void test_config_include__removing_include_removes_values(void)
@@ -132,6 +156,9 @@ void test_config_include__removing_include_removes_values(void)
cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
cl_git_mkfile("top-level", "");
cl_git_fail(git_config_get_string_buf(&buf, cfg, "foo.bar"));
+
+ cl_git_pass(p_unlink("top-level"));
+ cl_git_pass(p_unlink("included"));
}
void test_config_include__rewriting_include_refreshes_values(void)
@@ -145,6 +172,10 @@ void test_config_include__rewriting_include_refreshes_values(void)
cl_git_fail(git_config_get_string_buf(&buf, cfg, "foo.bar"));
cl_git_pass(git_config_get_string_buf(&buf, cfg, "first.other"));
cl_assert_equal_s(buf.ptr, "value");
+
+ cl_git_pass(p_unlink("top-level"));
+ cl_git_pass(p_unlink("first"));
+ cl_git_pass(p_unlink("second"));
}
void test_config_include__included_variables_cannot_be_deleted(void)
@@ -154,13 +185,20 @@ void test_config_include__included_variables_cannot_be_deleted(void)
cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
cl_git_fail(git_config_delete_entry(cfg, "foo.bar"));
+
+ cl_git_pass(p_unlink("top-level"));
+ cl_git_pass(p_unlink("included"));
}
void test_config_include__included_variables_cannot_be_modified(void)
{
cl_git_mkfile("top-level", "[include]\npath = included\n");
+
cl_git_mkfile("included", "[foo]\nbar = value");
cl_git_pass(git_config_open_ondisk(&cfg, "top-level"));
cl_git_fail(git_config_set_string(cfg, "foo.bar", "other-value"));
+
+ cl_git_pass(p_unlink("top-level"));
+ cl_git_pass(p_unlink("included"));
}
diff --git a/tests/core/vector.c b/tests/core/vector.c
index 6b8ea574d..2be7e86bd 100644
--- a/tests/core/vector.c
+++ b/tests/core/vector.c
@@ -412,7 +412,7 @@ void test_core_vector__dup_empty_vector(void)
{
git_vector v = GIT_VECTOR_INIT;
git_vector dup = GIT_VECTOR_INIT;
- void *dummy = 0xDEAFBEEB;
+ int dummy;
cl_assert_equal_i(0, v.length);
@@ -420,7 +420,7 @@ void test_core_vector__dup_empty_vector(void)
cl_assert_equal_i(0, dup._alloc_size);
cl_assert_equal_i(0, dup.length);
- cl_git_pass(git_vector_insert(&dup, dummy));
+ cl_git_pass(git_vector_insert(&dup, &dummy));
cl_assert_equal_i(8, dup._alloc_size);
cl_assert_equal_i(1, dup.length);
diff --git a/tests/submodule/inject_option.c b/tests/submodule/inject_option.c
new file mode 100644
index 000000000..182f088be
--- /dev/null
+++ b/tests/submodule/inject_option.c
@@ -0,0 +1,80 @@
+#include "clar_libgit2.h"
+#include "posix.h"
+#include "path.h"
+#include "submodule_helpers.h"
+#include "fileops.h"
+#include "repository.h"
+
+static git_repository *g_repo = NULL;
+
+void test_submodule_inject_option__initialize(void)
+{
+ g_repo = setup_fixture_submodule_simple();
+}
+
+void test_submodule_inject_option__cleanup(void)
+{
+ cl_git_sandbox_cleanup();
+}
+
+static int find_naughty(git_submodule *sm, const char *name, void *payload)
+{
+ int *foundit = (int *) payload;
+
+ GIT_UNUSED(sm);
+
+ if (!git__strcmp("naughty", name))
+ *foundit = true;
+
+ return 0;
+}
+
+void test_submodule_inject_option__url(void)
+{
+ int foundit;
+ git_submodule *sm;
+ git_buf buf = GIT_BUF_INIT;
+
+ cl_git_pass(git_buf_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
+ cl_git_rewritefile(buf.ptr,
+ "[submodule \"naughty\"]\n"
+ " path = testrepo\n"
+ " url = -u./payload\n");
+ git_buf_dispose(&buf);
+
+ /* We do want to find it, but with the appropriate field empty */
+ foundit = 0;
+ cl_git_pass(git_submodule_foreach(g_repo, find_naughty, &foundit));
+ cl_assert_equal_i(1, foundit);
+
+ cl_git_pass(git_submodule_lookup(&sm, g_repo, "naughty"));
+ cl_assert_equal_s("testrepo", git_submodule_path(sm));
+ cl_assert_equal_p(NULL, git_submodule_url(sm));
+
+ git_submodule_free(sm);
+}
+
+void test_submodule_inject_option__path(void)
+{
+ int foundit;
+ git_submodule *sm;
+ git_buf buf = GIT_BUF_INIT;
+
+ cl_git_pass(git_buf_joinpath(&buf, git_repository_workdir(g_repo), ".gitmodules"));
+ cl_git_rewritefile(buf.ptr,
+ "[submodule \"naughty\"]\n"
+ " path = --something\n"
+ " url = blah.git\n");
+ git_buf_dispose(&buf);
+
+ /* We do want to find it, but with the appropriate field empty */
+ foundit = 0;
+ cl_git_pass(git_submodule_foreach(g_repo, find_naughty, &foundit));
+ cl_assert_equal_i(1, foundit);
+
+ cl_git_pass(git_submodule_lookup(&sm, g_repo, "naughty"));
+ cl_assert_equal_s("naughty", git_submodule_path(sm));
+ cl_assert_equal_s("blah.git", git_submodule_url(sm));
+
+ git_submodule_free(sm);
+}
diff --git a/tests/transports/smart/packet.c b/tests/transports/smart/packet.c
new file mode 100644
index 000000000..5b623a378
--- /dev/null
+++ b/tests/transports/smart/packet.c
@@ -0,0 +1,340 @@
+#include "clar_libgit2.h"
+#include "transports/smart.h"
+
+enum expected_status {
+ PARSE_SUCCESS,
+ PARSE_FAILURE
+};
+
+static void assert_flush_parses(const char *line)
+{
+ size_t linelen = strlen(line) + 1;
+ const char *endptr;
+ git_pkt *pkt;
+
+ cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
+ cl_assert_equal_i(pkt->type, GIT_PKT_FLUSH);
+ cl_assert_equal_strn(endptr, line + 4, linelen - 4);
+
+ git_pkt_free((git_pkt *) pkt);
+}
+
+static void assert_data_pkt_parses(const char *line, const char *expected_data, size_t expected_len)
+{
+ size_t linelen = strlen(line) + 1;
+ const char *endptr;
+ git_pkt_data *pkt;
+
+ cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
+ cl_assert_equal_i(pkt->type, GIT_PKT_DATA);
+ cl_assert_equal_i(pkt->len, expected_len);
+ cl_assert_equal_strn(pkt->data, expected_data, expected_len);
+
+ git_pkt_free((git_pkt *) pkt);
+}
+
+static void assert_sideband_progress_parses(const char *line, const char *expected_data, size_t expected_len)
+{
+ size_t linelen = strlen(line) + 1;
+ const char *endptr;
+ git_pkt_progress *pkt;
+
+ cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
+ cl_assert_equal_i(pkt->type, GIT_PKT_PROGRESS);
+ cl_assert_equal_i(pkt->len, expected_len);
+ cl_assert_equal_strn(pkt->data, expected_data, expected_len);
+
+ git_pkt_free((git_pkt *) pkt);
+}
+
+static void assert_error_parses(const char *line, const char *expected_error, size_t expected_len)
+{
+ size_t linelen = strlen(line) + 1;
+ const char *endptr;
+ git_pkt_err *pkt;
+
+ cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
+ cl_assert_equal_i(pkt->type, GIT_PKT_ERR);
+ cl_assert_equal_i(pkt->len, expected_len);
+ cl_assert_equal_strn(pkt->error, expected_error, expected_len);
+
+ git_pkt_free((git_pkt *) pkt);
+}
+
+static void assert_ack_parses(const char *line, const char *expected_oid, enum git_ack_status expected_status)
+{
+ size_t linelen = strlen(line) + 1;
+ const char *endptr;
+ git_pkt_ack *pkt;
+ git_oid oid;
+
+ cl_git_pass(git_oid_fromstr(&oid, expected_oid));
+
+ cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
+ cl_assert_equal_i(pkt->type, GIT_PKT_ACK);
+ cl_assert_equal_oid(&pkt->oid, &oid);
+ cl_assert_equal_i(pkt->status, expected_status);
+
+ git_pkt_free((git_pkt *) pkt);
+}
+
+static void assert_nak_parses(const char *line)
+{
+ size_t linelen = strlen(line) + 1;
+ const char *endptr;
+ git_pkt *pkt;
+
+ cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
+ cl_assert_equal_i(pkt->type, GIT_PKT_NAK);
+ cl_assert_equal_strn(endptr, line + 7, linelen - 7);
+
+ git_pkt_free((git_pkt *) pkt);
+}
+
+static void assert_comment_parses(const char *line, const char *expected_comment)
+{
+ size_t linelen = strlen(line) + 1;
+ const char *endptr;
+ git_pkt_comment *pkt;
+
+ cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
+ cl_assert_equal_i(pkt->type, GIT_PKT_COMMENT);
+ cl_assert_equal_strn(pkt->comment, expected_comment, strlen(expected_comment));
+
+ git_pkt_free((git_pkt *) pkt);
+}
+
+static void assert_ok_parses(const char *line, const char *expected_ref)
+{
+ size_t linelen = strlen(line) + 1;
+ const char *endptr;
+ git_pkt_ok *pkt;
+
+ cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
+ cl_assert_equal_i(pkt->type, GIT_PKT_OK);
+ cl_assert_equal_strn(pkt->ref, expected_ref, strlen(expected_ref));
+
+ git_pkt_free((git_pkt *) pkt);
+}
+
+static void assert_unpack_parses(const char *line, bool ok)
+{
+ size_t linelen = strlen(line) + 1;
+ const char *endptr;
+ git_pkt_unpack *pkt;
+
+ cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
+ cl_assert_equal_i(pkt->type, GIT_PKT_UNPACK);
+ cl_assert_equal_i(pkt->unpack_ok, ok);
+
+ git_pkt_free((git_pkt *) pkt);
+}
+
+static void assert_ng_parses(const char *line, const char *expected_ref, const char *expected_msg)
+{
+ size_t linelen = strlen(line) + 1;
+ const char *endptr;
+ git_pkt_ng *pkt;
+
+ cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
+ cl_assert_equal_i(pkt->type, GIT_PKT_NG);
+ cl_assert_equal_strn(pkt->ref, expected_ref, strlen(expected_ref));
+ cl_assert_equal_strn(pkt->msg, expected_msg, strlen(expected_msg));
+
+ git_pkt_free((git_pkt *) pkt);
+}
+
+#define assert_ref_parses(line, expected_oid, expected_ref, expected_capabilities) \
+ assert_ref_parses_(line, sizeof(line), expected_oid, expected_ref, expected_capabilities)
+
+static void assert_ref_parses_(const char *line, size_t linelen, const char *expected_oid,
+ const char *expected_ref, const char *expected_capabilities)
+{
+ const char *endptr;
+ git_pkt_ref *pkt;
+ git_oid oid;
+
+ cl_git_pass(git_oid_fromstr(&oid, expected_oid));
+
+ cl_git_pass(git_pkt_parse_line((git_pkt **) &pkt, &endptr, line, linelen));
+ cl_assert_equal_i(pkt->type, GIT_PKT_REF);
+ cl_assert_equal_oid(&pkt->head.oid, &oid);
+ cl_assert_equal_strn(pkt->head.name, expected_ref, strlen(expected_ref));
+ if (expected_capabilities)
+ cl_assert_equal_strn(pkt->capabilities, expected_capabilities, strlen(expected_capabilities));
+ else
+ cl_assert_equal_p(NULL, pkt->capabilities);
+
+ git_pkt_free((git_pkt *) pkt);
+}
+
+static void assert_pkt_fails(const char *line)
+{
+ const char *endptr;
+ git_pkt *pkt;
+ cl_git_fail(git_pkt_parse_line(&pkt, &endptr, line, strlen(line) + 1));
+}
+
+void test_transports_smart_packet__parsing_garbage_fails(void)
+{
+ assert_pkt_fails("0foobar");
+ assert_pkt_fails("00foobar");
+ assert_pkt_fails("000foobar");
+ assert_pkt_fails("0001");
+ assert_pkt_fails("");
+ assert_pkt_fails("0");
+ assert_pkt_fails("0i00");
+ assert_pkt_fails("f");
+}
+
+void test_transports_smart_packet__flush_parses(void)
+{
+ assert_flush_parses("0000");
+ assert_flush_parses("0000foobar");
+}
+
+void test_transports_smart_packet__data_pkt(void)
+{
+ assert_pkt_fails("000foobar");
+ assert_pkt_fails("0001o");
+ assert_pkt_fails("0001\1");
+ assert_data_pkt_parses("0005\1", "", 0);
+ assert_pkt_fails("0009\1o");
+ assert_data_pkt_parses("0009\1data", "data", 4);
+ assert_data_pkt_parses("000a\1data", "data", 5);
+}
+
+void test_transports_smart_packet__sideband_progress_pkt(void)
+{
+ assert_pkt_fails("0001\2");
+ assert_sideband_progress_parses("0005\2", "", 0);
+ assert_pkt_fails("0009\2o");
+ assert_sideband_progress_parses("0009\2data", "data", 4);
+ assert_sideband_progress_parses("000a\2data", "data", 5);
+}
+
+void test_transports_smart_packet__sideband_err_pkt(void)
+{
+ assert_pkt_fails("0001\3");
+ assert_error_parses("0005\3", "", 0);
+ assert_pkt_fails("0009\3o");
+ assert_error_parses("0009\3data", "data", 4);
+ assert_error_parses("000a\3data", "data", 5);
+}
+
+void test_transports_smart_packet__ack_pkt(void)
+{
+ assert_ack_parses("0030ACK 0000000000000000000000000000000000000000",
+ "0000000000000000000000000000000000000000", 0);
+ assert_ack_parses("0039ACK 0000000000000000000000000000000000000000 continue",
+ "0000000000000000000000000000000000000000",
+ GIT_ACK_CONTINUE);
+ assert_ack_parses("0037ACK 0000000000000000000000000000000000000000 common",
+ "0000000000000000000000000000000000000000",
+ GIT_ACK_COMMON);
+ assert_ack_parses("0037ACK 0000000000000000000000000000000000000000 ready",
+ "0000000000000000000000000000000000000000",
+ GIT_ACK_READY);
+
+ /* these should fail as they don't have OIDs */
+ assert_pkt_fails("0007ACK");
+ assert_pkt_fails("0008ACK ");
+
+ /* this one is missing a space and should thus fail */
+ assert_pkt_fails("0036ACK00000000000000000x0000000000000000000000 ready");
+
+ /* the following ones have invalid OIDs and should thus fail */
+ assert_pkt_fails("0037ACK 00000000000000000x0000000000000000000000 ready");
+ assert_pkt_fails("0036ACK 000000000000000000000000000000000000000 ready");
+ assert_pkt_fails("0036ACK 00000000000000000x0000000000000000000000ready");
+
+ /* this one has an invalid status and should thus fail */
+ assert_pkt_fails("0036ACK 0000000000000000000000000000000000000000 read");
+}
+
+void test_transports_smart_packet__nak_pkt(void)
+{
+ assert_nak_parses("0007NAK");
+ assert_pkt_fails("0007NaK");
+ assert_pkt_fails("0007nak");
+ assert_nak_parses("0007NAKfoobar");
+ assert_pkt_fails("0007nakfoobar");
+ assert_pkt_fails("0007 NAK");
+}
+
+void test_transports_smart_packet__error_pkt(void)
+{
+ assert_pkt_fails("0007ERR");
+ assert_pkt_fails("0008ERRx");
+ assert_error_parses("0008ERR ", "", 0);
+ assert_error_parses("000EERR ERRMSG", "ERRMSG", 6);
+}
+
+void test_transports_smart_packet__comment_pkt(void)
+{
+ assert_comment_parses("0005#", "");
+ assert_comment_parses("000B#foobar", "#fooba");
+ assert_comment_parses("000C#foobar", "#foobar");
+ assert_comment_parses("001A#this is a comment\nfoo", "#this is a comment\nfoo");
+}
+
+void test_transports_smart_packet__ok_pkt(void)
+{
+ assert_pkt_fails("0007ok\n");
+ assert_ok_parses("0007ok ", "");
+ assert_ok_parses("0008ok \n", "");
+ assert_ok_parses("0008ok x", "x");
+ assert_ok_parses("0009ok x\n", "x");
+ assert_pkt_fails("001OK ref/foo/bar");
+ assert_ok_parses("0012ok ref/foo/bar", "ref/foo/bar");
+ assert_pkt_fails("0013OK ref/foo/bar\n");
+ assert_ok_parses("0013ok ref/foo/bar\n", "ref/foo/bar");
+}
+
+void test_transports_smart_packet__ng_pkt(void)
+{
+ /* TODO: same as for ok pkt */
+ assert_pkt_fails("0007ng\n");
+ assert_pkt_fails("0008ng \n");
+ assert_pkt_fails("000Bng ref\n");
+ assert_pkt_fails("000Bng ref\n");
+ /* TODO: is this a valid packet line? Probably not. */
+ assert_ng_parses("000Ang x\n", "", "x");
+ assert_ng_parses("000Fng ref msg\n", "ref", "msg");
+ assert_ng_parses("000Fng ref msg\n", "ref", "msg");
+}
+
+void test_transports_smart_packet__unpack_pkt(void)
+{
+ assert_unpack_parses("000Dunpack ok", 1);
+ assert_unpack_parses("000Dunpack ng error-msg", 0);
+ /* TODO: the following tests should fail */
+ assert_unpack_parses("000Aunpack", 0);
+ assert_unpack_parses("0011unpack foobar", 0);
+ assert_unpack_parses("0010unpack ng ok", 0);
+ assert_unpack_parses("0010unpack okfoo", 1);
+}
+
+void test_transports_smart_packet__ref_pkt(void)
+{
+ assert_pkt_fails("002C0000000000000000000000000000000000000000");
+ assert_pkt_fails("002D0000000000000000000000000000000000000000\n");
+ assert_pkt_fails("00300000000000000000000000000000000000000000HEAD");
+ assert_pkt_fails("004800000000x0000000000000000000000000000000 refs/heads/master\0multi_ack");
+ assert_ref_parses(
+ "003F0000000000000000000000000000000000000000 refs/heads/master\0",
+ "0000000000000000000000000000000000000000", "refs/heads/master", "");
+ assert_ref_parses(
+ "00480000000000000000000000000000000000000000 refs/heads/master\0multi_ack",
+ "0000000000000000000000000000000000000000", "refs/heads/master", "multi_ack");
+ assert_ref_parses(
+ "00460000000000000000000000000000000000000000 refs/heads/master\0one two",
+ "0000000000000000000000000000000000000000", "refs/heads/master", "one two");
+ assert_ref_parses(
+ "00310000000000000000000000000000000000000000 HEAD",
+ "0000000000000000000000000000000000000000", "HEAD", NULL);
+ assert_pkt_fails("0031000000000000000000000000000000000000000 HEAD");
+ assert_ref_parses(
+ "00360000000000000000000000000000000000000000 HEAD HEAD",
+ "0000000000000000000000000000000000000000", "HEAD HEAD", NULL);
+}