Commit 32d7abfc by Vicent Marti

Merge pull request #2091 from libgit2/rb/cleanups-123

Fix errors with zstream (and a variety of other cleanups)
parents 0316d80a 19459b1e
...@@ -183,7 +183,7 @@ GIT_EXTERN(int) git_blame_buffer( ...@@ -183,7 +183,7 @@ GIT_EXTERN(int) git_blame_buffer(
git_blame **out, git_blame **out,
git_blame *reference, git_blame *reference,
const char *buffer, const char *buffer,
uint32_t buffer_len); size_t buffer_len);
/** /**
* Free memory allocated by git_blame_file or git_blame_buffer. * Free memory allocated by git_blame_file or git_blame_buffer.
......
...@@ -196,13 +196,14 @@ GIT_EXTERN(int) git_blob_create_fromchunks( ...@@ -196,13 +196,14 @@ GIT_EXTERN(int) git_blob_create_fromchunks(
/** /**
* Write an in-memory buffer to the ODB as a blob * Write an in-memory buffer to the ODB as a blob
* *
* @param oid return the oid of the written blob * @param id return the id of the written blob
* @param repo repository where to blob will be written * @param repo repository where to blob will be written
* @param buffer data to be written into the blob * @param buffer data to be written into the blob
* @param len length of the data * @param len length of the data
* @return 0 or an error code * @return 0 or an error code
*/ */
GIT_EXTERN(int) git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *buffer, size_t len); GIT_EXTERN(int) git_blob_create_frombuffer(
git_oid *id, git_repository *repo, const void *buffer, size_t len);
/** /**
* Determine if the blob content is most certainly binary or not. * Determine if the blob content is most certainly binary or not.
......
...@@ -106,19 +106,6 @@ typedef enum { ...@@ -106,19 +106,6 @@ typedef enum {
GIT_SUBMODULE_STATUS_WD_UNTRACKED)) != 0) GIT_SUBMODULE_STATUS_WD_UNTRACKED)) != 0)
/** /**
* Options for submodule recurse.
*
* * GIT_SUBMODULE_RECURSE_NO - do no recurse into submodules
* * GIT_SUBMODULE_RECURSE_YES - recurse into submodules
* * GIT_SUBMODULE_RECURSE_ONDEMAND - recurse into submodules only when commit not already in local clone
*/
typedef enum {
GIT_SUBMODULE_RECURSE_NO = 0,
GIT_SUBMODULE_RECURSE_YES = 1,
GIT_SUBMODULE_RECURSE_ONDEMAND = 2,
} git_submodule_recurse_t;
/**
* Lookup submodule information by name or path. * Lookup submodule information by name or path.
* *
* Given either the submodule name or path (they are usually the same), this * Given either the submodule name or path (they are usually the same), this
......
...@@ -323,6 +323,25 @@ typedef enum { ...@@ -323,6 +323,25 @@ typedef enum {
GIT_SUBMODULE_IGNORE_DEFAULT = 0 GIT_SUBMODULE_IGNORE_DEFAULT = 0
} git_submodule_ignore_t; } git_submodule_ignore_t;
/**
* Options for submodule recurse.
*
* Represent the value of `submodule.$name.fetchRecurseSubmodules`
*
* * GIT_SUBMODULE_RECURSE_RESET - reset to the on-disk value
* * GIT_SUBMODULE_RECURSE_NO - do no recurse into submodules
* * GIT_SUBMODULE_RECURSE_YES - recurse into submodules
* * GIT_SUBMODULE_RECURSE_ONDEMAND - recurse into submodules only when
* commit not already in local clone
*/
typedef enum {
GIT_SUBMODULE_RECURSE_RESET = -1,
GIT_SUBMODULE_RECURSE_NO = 0,
GIT_SUBMODULE_RECURSE_YES = 1,
GIT_SUBMODULE_RECURSE_ONDEMAND = 2,
} git_submodule_recurse_t;
/** @} */ /** @} */
GIT_END_DECL GIT_END_DECL
......
...@@ -49,6 +49,8 @@ int git_attr_get( ...@@ -49,6 +49,8 @@ int git_attr_get(
git_attr_name attr; git_attr_name attr;
git_attr_rule *rule; git_attr_rule *rule;
assert(value && repo && name);
*value = NULL; *value = NULL;
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
...@@ -103,6 +105,11 @@ int git_attr_get_many( ...@@ -103,6 +105,11 @@ int git_attr_get_many(
attr_get_many_info *info = NULL; attr_get_many_info *info = NULL;
size_t num_found = 0; size_t num_found = 0;
if (!num_attr)
return 0;
assert(values && repo && names);
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
return -1; return -1;
...@@ -169,6 +176,8 @@ int git_attr_foreach( ...@@ -169,6 +176,8 @@ int git_attr_foreach(
git_attr_assignment *assign; git_attr_assignment *assign;
git_strmap *seen = NULL; git_strmap *seen = NULL;
assert(repo && callback);
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
return -1; return -1;
......
...@@ -450,7 +450,7 @@ int git_blame_buffer( ...@@ -450,7 +450,7 @@ int git_blame_buffer(
git_blame **out, git_blame **out,
git_blame *reference, git_blame *reference,
const char *buffer, const char *buffer,
uint32_t buffer_len) size_t buffer_len)
{ {
git_blame *blame; git_blame *blame;
git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT;
......
...@@ -50,25 +50,28 @@ int git_blob__parse(void *blob, git_odb_object *odb_obj) ...@@ -50,25 +50,28 @@ int git_blob__parse(void *blob, git_odb_object *odb_obj)
return 0; return 0;
} }
int git_blob_create_frombuffer(git_oid *oid, git_repository *repo, const void *buffer, size_t len) int git_blob_create_frombuffer(
git_oid *id, git_repository *repo, const void *buffer, size_t len)
{ {
int error; int error;
git_odb *odb; git_odb *odb;
git_odb_stream *stream; git_odb_stream *stream;
assert(id && repo);
if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 || if ((error = git_repository_odb__weakptr(&odb, repo)) < 0 ||
(error = git_odb_open_wstream(&stream, odb, len, GIT_OBJ_BLOB)) < 0) (error = git_odb_open_wstream(&stream, odb, len, GIT_OBJ_BLOB)) < 0)
return error; return error;
if ((error = git_odb_stream_write(stream, buffer, len)) == 0) if ((error = git_odb_stream_write(stream, buffer, len)) == 0)
error = git_odb_stream_finalize_write(oid, stream); error = git_odb_stream_finalize_write(id, stream);
git_odb_stream_free(stream); git_odb_stream_free(stream);
return error; return error;
} }
static int write_file_stream( static int write_file_stream(
git_oid *oid, git_odb *odb, const char *path, git_off_t file_size) git_oid *id, git_odb *odb, const char *path, git_off_t file_size)
{ {
int fd, error; int fd, error;
char buffer[4096]; char buffer[4096];
...@@ -97,14 +100,14 @@ static int write_file_stream( ...@@ -97,14 +100,14 @@ static int write_file_stream(
} }
if (!error) if (!error)
error = git_odb_stream_finalize_write(oid, stream); error = git_odb_stream_finalize_write(id, stream);
git_odb_stream_free(stream); git_odb_stream_free(stream);
return error; return error;
} }
static int write_file_filtered( static int write_file_filtered(
git_oid *oid, git_oid *id,
git_off_t *size, git_off_t *size,
git_odb *odb, git_odb *odb,
const char *full_path, const char *full_path,
...@@ -119,7 +122,7 @@ static int write_file_filtered( ...@@ -119,7 +122,7 @@ static int write_file_filtered(
if (!error) { if (!error) {
*size = tgt.size; *size = tgt.size;
error = git_odb_write(oid, odb, tgt.ptr, tgt.size, GIT_OBJ_BLOB); error = git_odb_write(id, odb, tgt.ptr, tgt.size, GIT_OBJ_BLOB);
} }
git_buf_free(&tgt); git_buf_free(&tgt);
...@@ -127,7 +130,7 @@ static int write_file_filtered( ...@@ -127,7 +130,7 @@ static int write_file_filtered(
} }
static int write_symlink( static int write_symlink(
git_oid *oid, git_odb *odb, const char *path, size_t link_size) git_oid *id, git_odb *odb, const char *path, size_t link_size)
{ {
char *link_data; char *link_data;
ssize_t read_len; ssize_t read_len;
...@@ -143,13 +146,13 @@ static int write_symlink( ...@@ -143,13 +146,13 @@ static int write_symlink(
return -1; return -1;
} }
error = git_odb_write(oid, odb, (void *)link_data, link_size, GIT_OBJ_BLOB); error = git_odb_write(id, odb, (void *)link_data, link_size, GIT_OBJ_BLOB);
git__free(link_data); git__free(link_data);
return error; return error;
} }
int git_blob__create_from_paths( int git_blob__create_from_paths(
git_oid *oid, git_oid *id,
struct stat *out_st, struct stat *out_st,
git_repository *repo, git_repository *repo,
const char *content_path, const char *content_path,
...@@ -188,7 +191,7 @@ int git_blob__create_from_paths( ...@@ -188,7 +191,7 @@ int git_blob__create_from_paths(
mode = hint_mode ? hint_mode : st.st_mode; mode = hint_mode ? hint_mode : st.st_mode;
if (S_ISLNK(mode)) { if (S_ISLNK(mode)) {
error = write_symlink(oid, odb, content_path, (size_t)size); error = write_symlink(id, odb, content_path, (size_t)size);
} else { } else {
git_filter_list *fl = NULL; git_filter_list *fl = NULL;
...@@ -202,10 +205,10 @@ int git_blob__create_from_paths( ...@@ -202,10 +205,10 @@ int git_blob__create_from_paths(
else if (fl == NULL) else if (fl == NULL)
/* No filters need to be applied to the document: we can stream /* No filters need to be applied to the document: we can stream
* directly from disk */ * directly from disk */
error = write_file_stream(oid, odb, content_path, size); error = write_file_stream(id, odb, content_path, size);
else { else {
/* We need to apply one or more filters */ /* We need to apply one or more filters */
error = write_file_filtered(oid, &size, odb, content_path, fl); error = write_file_filtered(id, &size, odb, content_path, fl);
git_filter_list_free(fl); git_filter_list_free(fl);
} }
...@@ -233,13 +236,13 @@ done: ...@@ -233,13 +236,13 @@ done:
} }
int git_blob_create_fromworkdir( int git_blob_create_fromworkdir(
git_oid *oid, git_repository *repo, const char *path) git_oid *id, git_repository *repo, const char *path)
{ {
return git_blob__create_from_paths(oid, NULL, repo, NULL, path, 0, true); return git_blob__create_from_paths(id, NULL, repo, NULL, path, 0, true);
} }
int git_blob_create_fromdisk( int git_blob_create_fromdisk(
git_oid *oid, git_repository *repo, const char *path) git_oid *id, git_repository *repo, const char *path)
{ {
int error; int error;
git_buf full_path = GIT_BUF_INIT; git_buf full_path = GIT_BUF_INIT;
...@@ -257,7 +260,7 @@ int git_blob_create_fromdisk( ...@@ -257,7 +260,7 @@ int git_blob_create_fromdisk(
hintpath += strlen(workdir); hintpath += strlen(workdir);
error = git_blob__create_from_paths( error = git_blob__create_from_paths(
oid, NULL, repo, git_buf_cstr(&full_path), hintpath, 0, true); id, NULL, repo, git_buf_cstr(&full_path), hintpath, 0, true);
git_buf_free(&full_path); git_buf_free(&full_path);
return error; return error;
...@@ -266,7 +269,7 @@ int git_blob_create_fromdisk( ...@@ -266,7 +269,7 @@ int git_blob_create_fromdisk(
#define BUFFER_SIZE 4096 #define BUFFER_SIZE 4096
int git_blob_create_fromchunks( int git_blob_create_fromchunks(
git_oid *oid, git_oid *id,
git_repository *repo, git_repository *repo,
const char *hintpath, const char *hintpath,
int (*source_cb)(char *content, size_t max_length, void *payload), int (*source_cb)(char *content, size_t max_length, void *payload),
...@@ -277,7 +280,7 @@ int git_blob_create_fromchunks( ...@@ -277,7 +280,7 @@ int git_blob_create_fromchunks(
git_filebuf file = GIT_FILEBUF_INIT; git_filebuf file = GIT_FILEBUF_INIT;
git_buf path = GIT_BUF_INIT; git_buf path = GIT_BUF_INIT;
assert(oid && repo && source_cb); assert(id && repo && source_cb);
if ((error = git_buf_joinpath( if ((error = git_buf_joinpath(
&path, git_repository_path(repo), GIT_OBJECTS_DIR "streamed")) < 0) &path, git_repository_path(repo), GIT_OBJECTS_DIR "streamed")) < 0)
...@@ -313,7 +316,7 @@ int git_blob_create_fromchunks( ...@@ -313,7 +316,7 @@ int git_blob_create_fromchunks(
goto cleanup; goto cleanup;
error = git_blob__create_from_paths( error = git_blob__create_from_paths(
oid, NULL, repo, file.path_lock, hintpath, 0, hintpath != NULL); id, NULL, repo, file.path_lock, hintpath, 0, hintpath != NULL);
cleanup: cleanup:
git_buf_free(&path); git_buf_free(&path);
......
...@@ -21,27 +21,22 @@ static int retrieve_branch_reference( ...@@ -21,27 +21,22 @@ static int retrieve_branch_reference(
const char *branch_name, const char *branch_name,
int is_remote) int is_remote)
{ {
git_reference *branch; git_reference *branch = NULL;
int error = -1; int error = 0;
char *prefix; char *prefix;
git_buf ref_name = GIT_BUF_INIT; git_buf ref_name = GIT_BUF_INIT;
*branch_reference_out = NULL;
prefix = is_remote ? GIT_REFS_REMOTES_DIR : GIT_REFS_HEADS_DIR; prefix = is_remote ? GIT_REFS_REMOTES_DIR : GIT_REFS_HEADS_DIR;
if (git_buf_joinpath(&ref_name, prefix, branch_name) < 0) if ((error = git_buf_joinpath(&ref_name, prefix, branch_name)) < 0)
goto cleanup; /* OOM */;
else if ((error = git_reference_lookup(&branch, repo, ref_name.ptr)) < 0)
giterr_set(
GITERR_REFERENCE, "Cannot locate %s branch '%s'",
is_remote ? "remote-tracking" : "local", branch_name);
if ((error = git_reference_lookup(&branch, repo, ref_name.ptr)) < 0) { *branch_reference_out = branch; /* will be NULL on error */
giterr_set(GITERR_REFERENCE,
"Cannot locate %s branch '%s'.", is_remote ? "remote-tracking" : "local", branch_name);
goto cleanup;
}
*branch_reference_out = branch;
cleanup:
git_buf_free(&ref_name); git_buf_free(&ref_name);
return error; return error;
} }
...@@ -63,21 +58,19 @@ int git_branch_create( ...@@ -63,21 +58,19 @@ int git_branch_create(
{ {
git_reference *branch = NULL; git_reference *branch = NULL;
git_buf canonical_branch_name = GIT_BUF_INIT; git_buf canonical_branch_name = GIT_BUF_INIT;
int error = -1; int error = 0;
assert(branch_name && commit && ref_out); assert(branch_name && commit && ref_out);
assert(git_object_owner((const git_object *)commit) == repository); assert(git_object_owner((const git_object *)commit) == repository);
if (git_buf_joinpath(&canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name) < 0) if (!(error = git_buf_joinpath(
goto cleanup; &canonical_branch_name, GIT_REFS_HEADS_DIR, branch_name)))
error = git_reference_create(
error = git_reference_create(&branch, repository, &branch, repository, git_buf_cstr(&canonical_branch_name),
git_buf_cstr(&canonical_branch_name), git_commit_id(commit), force, NULL, NULL); git_commit_id(commit), force, NULL, NULL);
if (!error) *ref_out = branch;
*ref_out = branch;
cleanup:
git_buf_free(&canonical_branch_name); git_buf_free(&canonical_branch_name);
return error; return error;
} }
......
...@@ -659,7 +659,7 @@ static int inject_object(git_indexer *idx, git_oid *id) ...@@ -659,7 +659,7 @@ static int inject_object(git_indexer *idx, git_oid *id)
hdr_len = git_packfile__object_header(hdr, len, git_odb_object_type(obj)); hdr_len = git_packfile__object_header(hdr, len, git_odb_object_type(obj));
git_filebuf_write(&idx->pack_file, hdr, hdr_len); git_filebuf_write(&idx->pack_file, hdr, hdr_len);
idx->pack->mwf.size += hdr_len; idx->pack->mwf.size += hdr_len;
entry->crc = crc32(entry->crc, hdr, hdr_len); entry->crc = crc32(entry->crc, hdr, (uInt)hdr_len);
if ((error = git_zstream_deflatebuf(&buf, data, len)) < 0) if ((error = git_zstream_deflatebuf(&buf, data, len)) < 0)
goto cleanup; goto cleanup;
......
...@@ -291,7 +291,6 @@ static int write_object( ...@@ -291,7 +291,6 @@ static int write_object(
void *delta_data = NULL; void *delta_data = NULL;
void *data; void *data;
size_t hdr_len, zbuf_len = COMPRESS_BUFLEN, data_len; size_t hdr_len, zbuf_len = COMPRESS_BUFLEN, data_len;
ssize_t written;
int error; int error;
if (po->delta) { if (po->delta) {
...@@ -337,19 +336,15 @@ static int write_object( ...@@ -337,19 +336,15 @@ static int write_object(
GITERR_CHECK_ALLOC(zbuf); GITERR_CHECK_ALLOC(zbuf);
git_zstream_reset(&pb->zstream); git_zstream_reset(&pb->zstream);
git_zstream_set_input(&pb->zstream, data, data_len);
while ((written = git_zstream_deflate(zbuf, zbuf_len, &pb->zstream, data, data_len)) > 0) { while (!git_zstream_done(&pb->zstream)) {
if ((error = write_cb(zbuf, written, cb_data)) < 0 || if ((error = git_zstream_get_output(zbuf, &zbuf_len, &pb->zstream)) < 0 ||
(error = git_hash_update(&pb->ctx, zbuf, written)) < 0) (error = write_cb(zbuf, zbuf_len, cb_data)) < 0 ||
(error = git_hash_update(&pb->ctx, zbuf, zbuf_len)) < 0)
goto done; goto done;
data = (char *)data + written; zbuf_len = COMPRESS_BUFLEN; /* reuse buffer */
data_len -= written;
}
if (written < 0) {
error = written;
goto done;
} }
if (po->delta) if (po->delta)
......
...@@ -498,6 +498,7 @@ int git_submodule_save(git_submodule *submodule) ...@@ -498,6 +498,7 @@ int git_submodule_save(git_submodule *submodule)
submodule->ignore_default = submodule->ignore; submodule->ignore_default = submodule->ignore;
submodule->update_default = submodule->update; submodule->update_default = submodule->update;
submodule->fetch_recurse_default = submodule->fetch_recurse;
submodule->flags |= GIT_SUBMODULE_STATUS_IN_CONFIG; submodule->flags |= GIT_SUBMODULE_STATUS_IN_CONFIG;
cleanup: cleanup:
...@@ -650,6 +651,9 @@ git_submodule_recurse_t git_submodule_set_fetch_recurse_submodules( ...@@ -650,6 +651,9 @@ git_submodule_recurse_t git_submodule_set_fetch_recurse_submodules(
assert(submodule); assert(submodule);
if (fetch_recurse_submodules == GIT_SUBMODULE_RECURSE_RESET)
fetch_recurse_submodules = submodule->fetch_recurse_default;
old = submodule->fetch_recurse; old = submodule->fetch_recurse;
submodule->fetch_recurse = fetch_recurse_submodules; submodule->fetch_recurse = fetch_recurse_submodules;
return old; return old;
...@@ -1000,7 +1004,7 @@ static git_submodule *submodule_alloc(git_repository *repo, const char *name) ...@@ -1000,7 +1004,7 @@ static git_submodule *submodule_alloc(git_repository *repo, const char *name)
GIT_REFCOUNT_INC(sm); GIT_REFCOUNT_INC(sm);
sm->ignore = sm->ignore_default = GIT_SUBMODULE_IGNORE_NONE; sm->ignore = sm->ignore_default = GIT_SUBMODULE_IGNORE_NONE;
sm->update = sm->update_default = GIT_SUBMODULE_UPDATE_CHECKOUT; sm->update = sm->update_default = GIT_SUBMODULE_UPDATE_CHECKOUT;
sm->fetch_recurse = GIT_SUBMODULE_RECURSE_YES; sm->fetch_recurse = sm->fetch_recurse_default = GIT_SUBMODULE_RECURSE_NO;
sm->repo = repo; sm->repo = repo;
sm->branch = NULL; sm->branch = NULL;
...@@ -1218,6 +1222,7 @@ static int submodule_load_from_config( ...@@ -1218,6 +1222,7 @@ static int submodule_load_from_config(
else if (strcasecmp(property, "fetchRecurseSubmodules") == 0) { else if (strcasecmp(property, "fetchRecurseSubmodules") == 0) {
if (git_submodule_parse_recurse(&sm->fetch_recurse, value) < 0) if (git_submodule_parse_recurse(&sm->fetch_recurse, value) < 0)
return -1; return -1;
sm->fetch_recurse_default = sm->fetch_recurse;
} }
else if (strcasecmp(property, "ignore") == 0) { else if (strcasecmp(property, "ignore") == 0) {
if ((error = git_submodule_parse_ignore(&sm->ignore, value)) < 0) if ((error = git_submodule_parse_ignore(&sm->ignore, value)) < 0)
......
...@@ -60,7 +60,9 @@ ...@@ -60,7 +60,9 @@
* - `update_default` is the update value from the config * - `update_default` is the update value from the config
* - `ignore` is a git_submodule_ignore_t value - see gitmodules(5) ignore. * - `ignore` is a git_submodule_ignore_t value - see gitmodules(5) ignore.
* - `ignore_default` is the ignore value from the config * - `ignore_default` is the ignore value from the config
* - `fetch_recurse` is 0 or 1 - see gitmodules(5) fetchRecurseSubmodules. * - `fetch_recurse` is a git_submodule_recurse_t value - see gitmodules(5)
* fetchRecurseSubmodules.
* - `fetch_recurse_default` is the recurse value from the config
* *
* - `repo` is the parent repository that contains this submodule. * - `repo` is the parent repository that contains this submodule.
* - `flags` after for internal use, tracking where this submodule has been * - `flags` after for internal use, tracking where this submodule has been
...@@ -87,6 +89,7 @@ struct git_submodule { ...@@ -87,6 +89,7 @@ struct git_submodule {
git_submodule_ignore_t ignore; git_submodule_ignore_t ignore;
git_submodule_ignore_t ignore_default; git_submodule_ignore_t ignore_default;
git_submodule_recurse_t fetch_recurse; git_submodule_recurse_t fetch_recurse;
git_submodule_recurse_t fetch_recurse_default;
/* internal information */ /* internal information */
git_repository *repo; git_repository *repo;
......
...@@ -193,9 +193,9 @@ PATTERNS("php", ...@@ -193,9 +193,9 @@ PATTERNS("php",
"|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"), "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
PATTERNS("javascript", PATTERNS("javascript",
"^[ \t]*(function[ \t][a-zA-Z_][^\{]*)\n" "^[ \t]*(function[ \t][a-zA-Z_][^\\{]*)\n"
"^[ \t]*(var[ \t]+[a-zA-Z_][a-zA-Z0-9_]*[ \t]*=[ \t]*function[ \t\(][^\{]*)\n" "^[ \t]*(var[ \t]+[a-zA-Z_][a-zA-Z0-9_]*[ \t]*=[ \t]*function[ \t\\(][^\\{]*)\n"
"^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*[ \t]*:[ \t]*function[ \t\(][^\{]*)", "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*[ \t]*:[ \t]*function[ \t\\(][^\\{]*)",
/* -- */ /* -- */
"[a-zA-Z_][a-zA-Z0-9_]*" "[a-zA-Z_][a-zA-Z0-9_]*"
"|[-+0-9.e]+[fFlL]?|0[xX]?[0-9a-fA-F]+[lL]?" "|[-+0-9.e]+[fFlL]?|0[xX]?[0-9a-fA-F]+[lL]?"
......
...@@ -10,14 +10,18 @@ ...@@ -10,14 +10,18 @@
#include "zstream.h" #include "zstream.h"
#include "buffer.h" #include "buffer.h"
#define BUFFER_SIZE (1024 * 1024) #define ZSTREAM_BUFFER_SIZE (1024 * 1024)
#define ZSTREAM_BUFFER_MIN_EXTRA 8
static int zstream_seterr(int zerr, git_zstream *zstream) static int zstream_seterr(git_zstream *zs)
{ {
if (zerr == Z_MEM_ERROR) if (zs->zerr == Z_OK || zs->zerr == Z_STREAM_END)
return 0;
if (zs->zerr == Z_MEM_ERROR)
giterr_set_oom(); giterr_set_oom();
else if (zstream->msg) else if (zs->z.msg)
giterr_set(GITERR_ZLIB, zstream->msg); giterr_set(GITERR_ZLIB, zs->z.msg);
else else
giterr_set(GITERR_ZLIB, "Unknown compression error"); giterr_set(GITERR_ZLIB, "Unknown compression error");
...@@ -26,69 +30,127 @@ static int zstream_seterr(int zerr, git_zstream *zstream) ...@@ -26,69 +30,127 @@ static int zstream_seterr(int zerr, git_zstream *zstream)
int git_zstream_init(git_zstream *zstream) int git_zstream_init(git_zstream *zstream)
{ {
int zerr; zstream->zerr = deflateInit(&zstream->z, Z_DEFAULT_COMPRESSION);
return zstream_seterr(zstream);
if ((zerr = deflateInit(zstream, Z_DEFAULT_COMPRESSION)) != Z_OK)
return zstream_seterr(zerr, zstream);
return 0;
} }
ssize_t git_zstream_deflate(void *out, size_t out_len, git_zstream *zstream, const void *in, size_t in_len) void git_zstream_free(git_zstream *zstream)
{ {
int zerr; deflateEnd(&zstream->z);
}
if ((ssize_t)out_len < 0)
out_len = INT_MAX;
zstream->next_in = (Bytef *)in; void git_zstream_reset(git_zstream *zstream)
zstream->avail_in = in_len; {
zstream->next_out = out; deflateReset(&zstream->z);
zstream->avail_out = out_len; zstream->in = NULL;
zstream->in_len = 0;
zstream->zerr = Z_STREAM_END;
}
if ((zerr = deflate(zstream, Z_FINISH)) == Z_STREAM_ERROR) int git_zstream_set_input(git_zstream *zstream, const void *in, size_t in_len)
return zstream_seterr(zerr, zstream); {
zstream->in = in;
zstream->in_len = in_len;
zstream->zerr = Z_OK;
return 0;
}
return (out_len - zstream->avail_out); bool git_zstream_done(git_zstream *zstream)
{
return (!zstream->in_len && zstream->zerr == Z_STREAM_END);
} }
void git_zstream_reset(git_zstream *zstream) size_t git_zstream_suggest_output_len(git_zstream *zstream)
{ {
deflateReset(zstream); if (zstream->in_len > ZSTREAM_BUFFER_SIZE)
return ZSTREAM_BUFFER_SIZE;
else if (zstream->in_len > ZSTREAM_BUFFER_MIN_EXTRA)
return zstream->in_len;
else
return ZSTREAM_BUFFER_MIN_EXTRA;
} }
void git_zstream_free(git_zstream *zstream) int git_zstream_get_output(void *out, size_t *out_len, git_zstream *zstream)
{ {
deflateEnd(zstream); int zflush = Z_FINISH;
size_t out_remain = *out_len;
while (out_remain > 0 && zstream->zerr != Z_STREAM_END) {
size_t out_queued, in_queued, out_used, in_used;
/* set up in data */
zstream->z.next_in = (Bytef *)zstream->in;
zstream->z.avail_in = (uInt)zstream->in_len;
if ((size_t)zstream->z.avail_in != zstream->in_len) {
zstream->z.avail_in = INT_MAX;
zflush = Z_NO_FLUSH;
} else {
zflush = Z_FINISH;
}
in_queued = (size_t)zstream->z.avail_in;
/* set up out data */
zstream->z.next_out = out;
zstream->z.avail_out = (uInt)out_remain;
if ((size_t)zstream->z.avail_out != out_remain)
zstream->z.avail_out = INT_MAX;
out_queued = (size_t)zstream->z.avail_out;
/* compress next chunk */
zstream->zerr = deflate(&zstream->z, zflush);
if (zstream->zerr == Z_STREAM_ERROR)
return zstream_seterr(zstream);
out_used = (out_queued - zstream->z.avail_out);
out_remain -= out_used;
out = ((char *)out) + out_used;
in_used = (in_queued - zstream->z.avail_in);
zstream->in_len -= in_used;
zstream->in += in_used;
}
/* either we finished the input or we did not flush the data */
assert(zstream->in_len > 0 || zflush == Z_FINISH);
/* set out_size to number of bytes actually written to output */
*out_len = *out_len - out_remain;
return 0;
} }
int git_zstream_deflatebuf(git_buf *out, const void *in, size_t in_len) int git_zstream_deflatebuf(git_buf *out, const void *in, size_t in_len)
{ {
git_zstream zstream = GIT_ZSTREAM_INIT; git_zstream zs = GIT_ZSTREAM_INIT;
size_t out_len;
ssize_t written;
int error = 0; int error = 0;
if ((error = git_zstream_init(&zstream)) < 0) if ((error = git_zstream_init(&zs)) < 0)
return error; return error;
do { if ((error = git_zstream_set_input(&zs, in, in_len)) < 0)
if (out->asize - out->size < BUFFER_SIZE) goto done;
git_buf_grow(out, out->asize + BUFFER_SIZE);
while (!git_zstream_done(&zs)) {
size_t step = git_zstream_suggest_output_len(&zs), written;
if ((error = git_buf_grow(out, out->asize + step)) < 0)
goto done;
out_len = out->asize - out->size; written = out->asize - out->size;
if ((written = git_zstream_deflate(out->ptr + out->size, out_len, &zstream, in, in_len)) <= 0) if ((error = git_zstream_get_output(
break; out->ptr + out->size, &written, &zs)) < 0)
goto done;
in = (char *)in + written;
in_len -= written;
out->size += written; out->size += written;
} while (written > 0); }
if (written < 0) /* NULL terminate for consistency if possible */
error = written; if (out->size < out->asize)
out->ptr[out->size] = '\0';
git_zstream_free(&zstream); done:
git_zstream_free(&zs);
return error; return error;
} }
...@@ -12,15 +12,28 @@ ...@@ -12,15 +12,28 @@
#include "common.h" #include "common.h"
#include "buffer.h" #include "buffer.h"
#define git_zstream z_stream typedef struct {
z_stream z;
const char *in;
size_t in_len;
int zerr;
} git_zstream;
#define GIT_ZSTREAM_INIT {0} #define GIT_ZSTREAM_INIT {{0}}
int git_zstream_init(git_zstream *zstream); int git_zstream_init(git_zstream *zstream);
ssize_t git_zstream_deflate(void *out, size_t out_len, git_zstream *zstream, const void *in, size_t in_len);
void git_zstream_reset(git_zstream *zstream);
void git_zstream_free(git_zstream *zstream); void git_zstream_free(git_zstream *zstream);
int git_zstream_set_input(git_zstream *zstream, const void *in, size_t in_len);
size_t git_zstream_suggest_output_len(git_zstream *zstream);
int git_zstream_get_output(void *out, size_t *out_len, git_zstream *zstream);
bool git_zstream_done(git_zstream *zstream);
void git_zstream_reset(git_zstream *zstream);
int git_zstream_deflatebuf(git_buf *out, const void *in, size_t in_len); int git_zstream_deflatebuf(git_buf *out, const void *in, size_t in_len);
#endif /* INCLUDE_zstream_h__ */ #endif /* INCLUDE_zstream_h__ */
#include "clar_libgit2.h"
#include "buffer.h"
#include "zstream.h"
static const char *data = "This is a test test test of This is a test";
#define INFLATE_EXTRA 2
static void assert_zlib_equal_(
const void *expected, size_t e_len,
const void *compressed, size_t c_len,
const char *msg, const char *file, int line)
{
z_stream stream;
char *expanded = git__calloc(1, e_len + INFLATE_EXTRA);
cl_assert(expanded);
memset(&stream, 0, sizeof(stream));
stream.next_out = (Bytef *)expanded;
stream.avail_out = (uInt)(e_len + INFLATE_EXTRA);
stream.next_in = (Bytef *)compressed;
stream.avail_in = (uInt)c_len;
cl_assert(inflateInit(&stream) == Z_OK);
cl_assert(inflate(&stream, Z_FINISH));
inflateEnd(&stream);
clar__assert_equal(
file, line, msg, 1,
"%d", (int)stream.total_out, (int)e_len);
clar__assert_equal(
file, line, "Buffer len was not exact match", 1,
"%d", (int)stream.avail_out, (int)INFLATE_EXTRA);
clar__assert(
memcmp(expanded, expected, e_len) == 0,
file, line, "uncompressed data did not match", NULL, 1);
git__free(expanded);
}
#define assert_zlib_equal(E,EL,C,CL) \
assert_zlib_equal_(E, EL, C, CL, #EL " != " #CL, __FILE__, (int)__LINE__)
void test_core_zstream__basic(void)
{
git_zstream z = GIT_ZSTREAM_INIT;
char out[128];
size_t outlen = sizeof(out);
cl_git_pass(git_zstream_init(&z));
cl_git_pass(git_zstream_set_input(&z, data, strlen(data) + 1));
cl_git_pass(git_zstream_get_output(out, &outlen, &z));
cl_assert(git_zstream_done(&z));
cl_assert(outlen > 0);
git_zstream_free(&z);
assert_zlib_equal(data, strlen(data) + 1, out, outlen);
}
void test_core_zstream__buffer(void)
{
git_buf out = GIT_BUF_INIT;
cl_git_pass(git_zstream_deflatebuf(&out, data, strlen(data) + 1));
assert_zlib_equal(data, strlen(data) + 1, out.ptr, out.size);
git_buf_free(&out);
}
#define BIG_STRING_PART "Big Data IS Big - Long Data IS Long - We need a buffer larger than 1024 x 1024 to make sure we trigger chunked compression - Big Big Data IS Bigger than Big - Long Long Data IS Longer than Long"
static void compress_input_various_ways(git_buf *input)
{
git_buf out1 = GIT_BUF_INIT, out2 = GIT_BUF_INIT;
size_t i, fixed_size = max(input->size / 2, 256);
char *fixed = git__malloc(fixed_size);
cl_assert(fixed);
/* compress with deflatebuf */
cl_git_pass(git_zstream_deflatebuf(&out1, input->ptr, input->size));
assert_zlib_equal(input->ptr, input->size, out1.ptr, out1.size);
/* compress with various fixed size buffer (accumulating the output) */
for (i = 0; i < 3; ++i) {
git_zstream zs = GIT_ZSTREAM_INIT;
size_t use_fixed_size;
switch (i) {
case 0: use_fixed_size = 256; break;
case 1: use_fixed_size = fixed_size / 2; break;
case 2: use_fixed_size = fixed_size; break;
}
cl_assert(use_fixed_size <= fixed_size);
cl_git_pass(git_zstream_init(&zs));
cl_git_pass(git_zstream_set_input(&zs, input->ptr, input->size));
while (!git_zstream_done(&zs)) {
size_t written = use_fixed_size;
cl_git_pass(git_zstream_get_output(fixed, &written, &zs));
cl_git_pass(git_buf_put(&out2, fixed, written));
}
git_zstream_free(&zs);
assert_zlib_equal(input->ptr, input->size, out2.ptr, out2.size);
/* did both approaches give the same data? */
cl_assert_equal_sz(out1.size, out2.size);
cl_assert(!memcmp(out1.ptr, out2.ptr, out1.size));
git_buf_free(&out2);
}
git_buf_free(&out1);
git__free(fixed);
}
void test_core_zstream__big_data(void)
{
git_buf in = GIT_BUF_INIT;
size_t scan, target;
for (target = 1024; target <= 1024 * 1024 * 4; target *= 8) {
/* make a big string that's easy to compress */
git_buf_clear(&in);
while (in.size < target)
cl_git_pass(
git_buf_put(&in, BIG_STRING_PART, strlen(BIG_STRING_PART)));
compress_input_various_ways(&in);
/* make a big string that's hard to compress */
srand(0xabad1dea);
for (scan = 0; scan < in.size; ++scan)
in.ptr[scan] = (char)rand();
compress_input_various_ways(&in);
}
git_buf_free(&in);
}
...@@ -560,7 +560,6 @@ void test_status_renames__zero_byte_file_does_not_fail(void) ...@@ -560,7 +560,6 @@ void test_status_renames__zero_byte_file_does_not_fail(void)
{ {
git_status_list *statuslist; git_status_list *statuslist;
git_status_options opts = GIT_STATUS_OPTIONS_INIT; git_status_options opts = GIT_STATUS_OPTIONS_INIT;
status_entry_counts counts = {0};
struct status_entry expected[] = { struct status_entry expected[] = {
{ GIT_STATUS_WT_DELETED, "ikeepsix.txt", "ikeepsix.txt" }, { GIT_STATUS_WT_DELETED, "ikeepsix.txt", "ikeepsix.txt" },
......
...@@ -178,25 +178,28 @@ void test_submodule_modify__edit_and_save(void) ...@@ -178,25 +178,28 @@ void test_submodule_modify__edit_and_save(void)
cl_git_pass(git_submodule_set_url(sm1, SM_LIBGIT2_URL)); cl_git_pass(git_submodule_set_url(sm1, SM_LIBGIT2_URL));
old_ignore = git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_UNTRACKED); old_ignore = git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_UNTRACKED);
old_update = git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_REBASE); old_update = git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_REBASE);
old_fetchrecurse = git_submodule_set_fetch_recurse_submodules(sm1, GIT_SUBMODULE_RECURSE_YES); old_fetchrecurse = git_submodule_set_fetch_recurse_submodules(
sm1, GIT_SUBMODULE_RECURSE_YES);
cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm1)); cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm1));
cl_assert_equal_i( cl_assert_equal_i(
(int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm1)); GIT_SUBMODULE_IGNORE_UNTRACKED, git_submodule_ignore(sm1));
cl_assert_equal_i( cl_assert_equal_i(
(int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm1)); GIT_SUBMODULE_UPDATE_REBASE, git_submodule_update(sm1));
cl_assert_equal_i(GIT_SUBMODULE_RECURSE_YES, git_submodule_fetch_recurse_submodules(sm1)); cl_assert_equal_i(
GIT_SUBMODULE_RECURSE_YES, git_submodule_fetch_recurse_submodules(sm1));
/* revert without saving (and confirm setters return old value) */ /* revert without saving (and confirm setters return old value) */
cl_git_pass(git_submodule_set_url(sm1, old_url)); cl_git_pass(git_submodule_set_url(sm1, old_url));
cl_assert_equal_i( cl_assert_equal_i(
(int)GIT_SUBMODULE_IGNORE_UNTRACKED, GIT_SUBMODULE_IGNORE_UNTRACKED,
(int)git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_RESET)); git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_RESET));
cl_assert_equal_i( cl_assert_equal_i(
(int)GIT_SUBMODULE_UPDATE_REBASE, GIT_SUBMODULE_UPDATE_REBASE,
(int)git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_RESET)); git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_RESET));
cl_assert_equal_i( cl_assert_equal_i(
GIT_SUBMODULE_RECURSE_YES, git_submodule_set_fetch_recurse_submodules(sm1, old_fetchrecurse)); GIT_SUBMODULE_RECURSE_YES, git_submodule_set_fetch_recurse_submodules(
sm1, GIT_SUBMODULE_RECURSE_RESET));
/* check that revert was successful */ /* check that revert was successful */
cl_assert_equal_s(old_url, git_submodule_url(sm1)); cl_assert_equal_s(old_url, git_submodule_url(sm1));
...@@ -243,19 +246,22 @@ void test_submodule_modify__edit_and_save(void) ...@@ -243,19 +246,22 @@ void test_submodule_modify__edit_and_save(void)
cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm2)); cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm2));
cl_assert_equal_i( cl_assert_equal_i(
(int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm2)); GIT_SUBMODULE_IGNORE_UNTRACKED, git_submodule_ignore(sm2));
cl_assert_equal_i( cl_assert_equal_i(
(int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm2)); GIT_SUBMODULE_UPDATE_REBASE, git_submodule_update(sm2));
cl_assert_equal_i(GIT_SUBMODULE_RECURSE_YES, git_submodule_fetch_recurse_submodules(sm2)); cl_assert_equal_i(
GIT_SUBMODULE_RECURSE_NO, git_submodule_fetch_recurse_submodules(sm2));
/* set fetchRecurseSubmodules on-demand */ /* set fetchRecurseSubmodules on-demand */
cl_git_pass(git_submodule_reload(sm1)); cl_git_pass(git_submodule_reload(sm1));
git_submodule_set_fetch_recurse_submodules(sm1, GIT_SUBMODULE_RECURSE_ONDEMAND); git_submodule_set_fetch_recurse_submodules(sm1, GIT_SUBMODULE_RECURSE_ONDEMAND);
cl_assert_equal_i(GIT_SUBMODULE_RECURSE_ONDEMAND, git_submodule_fetch_recurse_submodules(sm1)); cl_assert_equal_i(
GIT_SUBMODULE_RECURSE_ONDEMAND, git_submodule_fetch_recurse_submodules(sm1));
/* call save */ /* call save */
cl_git_pass(git_submodule_save(sm1)); cl_git_pass(git_submodule_save(sm1));
cl_git_pass(git_submodule_reload(sm1)); cl_git_pass(git_submodule_reload(sm1));
cl_assert_equal_i(GIT_SUBMODULE_RECURSE_ONDEMAND, git_submodule_fetch_recurse_submodules(sm1)); cl_assert_equal_i(
GIT_SUBMODULE_RECURSE_ONDEMAND, git_submodule_fetch_recurse_submodules(sm1));
git_repository_free(r2); git_repository_free(r2);
git__free(old_url); git__free(old_url);
......
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