/* * Try to open the url as a git directory. The direction doesn't * matter in this case because we're calulating the heads ourselves. */ static int local_connect(git_transport *transport, int GIT_UNUSED(direction)) { git_repository *repo; int error; transport_local *t = (transport_local *) transport; const char *path; const char file_prefix[] = "file://"; GIT_UNUSED_ARG(direction); /* The repo layer doesn't want the prefix */ if (!git__prefixcmp(transport->url, file_prefix)) path = transport->url + STRLEN(file_prefix); else path = transport->url; error = git_repository_open(&repo, path); if (error < GIT_SUCCESS) return git__rethrow(error, "Failed to open remote"); t->repo = repo; t->parent.connected = 1; return GIT_SUCCESS; }
int git_repository_init(git_repository **repo_out, const char *path, unsigned is_bare) { int error = GIT_SUCCESS; repo_init results; assert(repo_out && path); results.path_repository = NULL; results.is_bare = is_bare; error = repo_init_find_dir(&results, path); if (error < GIT_SUCCESS) goto cleanup; error = repo_init_structure(&results); if (error < GIT_SUCCESS) goto cleanup; error = git_repository_open(repo_out, results.path_repository); cleanup: free(results.path_repository); return error; }
int edit_repo(const char *repo_name) { int r; git_repository *repo; git_oid blob_id; git_oid oid; git_oid tree_id; git_signature *author; git_time_t time; git_config *config; git_index *index; git_tree *tree; git_treebuilder *tree_builder; git_treebuilder *empty_tree_builder; git_reference *head; git_commit *commit_parents[1]; char global_config_path[GIT_PATH_MAX]; char out[41]; out[40] = '\0'; // create the repository r = git_repository_open(&repo, repo_name); if (r) printf("error in opening repository\n"); printf("Repo opened\n"); // create a treebuilder r = git_treebuilder_create(&tree_builder, NULL); if (r) printf("error in creting treebuilder\n"); printf("Tree builder created\n"); // ADDING FIRST FILE // create a blob r = git_blob_create_fromdisk(&blob_id, repo, "test2"); if (r) printf("error in creating blob from disk\n"); printf("Blob created\n"); // insert into tree r = git_treebuilder_insert(NULL, tree_builder, "test1", &blob_id, 0100644); if (r) printf("error in inserting into treebuilder\n"); printf("Insert into treebuilder successful\n"); // write the tree to the repo r = git_treebuilder_write(&oid, repo, tree_builder); if (r) printf("error in writing the tree to the repo\n"); printf("Writing the tree to repo successful\n"); // tree lookup r = git_tree_lookup(&tree, repo, &oid); if (r) printf("error in tree lookup\n"); printf("Tree lookup done\n"); // create a author time = get_time(); r = git_signature_new(&author, "Varun Agrawal", "*****@*****.**", time, -300); if (r) printf("error in creating signature\n"); printf("Author signature created\n"); // obtaining the head r = git_repository_head(&head, repo); if (r) printf("error in obtaining the head\n"); r = git_reference_name_to_oid(&oid, repo, git_reference_name(head)); if (r) printf("error in obtaining the ref id of head\n"); printf("Obtained the head id %s\n", git_oid_tostr(out, 41, &oid)); git_commit_lookup(&commit_parents[0], repo, &oid); // create a commit r = git_commit_create( &oid, // object id repo, // repository "HEAD", // update reference, this will update the HEAD to this commit author, // author author, // committer NULL, // message encoding, by default UTF-8 is used "second commit", // message for the commit tree, // the git_tree object which will be used as the tree for this commit. don't know if NULL is valid 1, // number of parents. Don't know what value should be used here commit_parents); // array of pointers to the parents(git_commit *parents[]) if (r) printf("error in creating a commit\n"); printf("Commit created\n"); git_repository_free(repo); return 0; }
int main (int argc, char** argv) { // ### Opening the Repository // There are a couple of methods for opening a repository, this being the simplest. // There are also [methods][me] for specifying the index file and work tree locations, here // we are assuming they are in the normal places. // // [me]: http://libgit2.github.com/libgit2/#HEAD/group/repository git_repository *repo; if (argc > 1) { git_repository_open(&repo, argv[1]); } else { git_repository_open(&repo, "/opt/libgit2-test/.git"); } // ### SHA-1 Value Conversions // For our first example, we will convert a 40 character hex value to the 20 byte raw SHA1 value. printf("*Hex to Raw*\n"); char hex[] = "fd6e612585290339ea8bf39c692a7ff6a29cb7c3"; // The `git_oid` is the structure that keeps the SHA value. We will use this throughout the example // for storing the value of the current SHA key we're working with. git_oid oid; git_oid_fromstr(&oid, hex); // Once we've converted the string into the oid value, we can get the raw value of the SHA. printf("Raw 20 bytes: [%.20s]\n", (&oid)->id); // Next we will convert the 20 byte raw SHA1 value to a human readable 40 char hex value. printf("\n*Raw to Hex*\n"); char out[41]; out[40] = '\0'; // If you have a oid, you can easily get the hex value of the SHA as well. git_oid_fmt(out, &oid); printf("SHA hex string: %s\n", out); // ### Working with the Object Database // **libgit2** provides [direct access][odb] to the object database. // The object database is where the actual objects are stored in Git. For // working with raw objects, we'll need to get this structure from the // repository. // [odb]: http://libgit2.github.com/libgit2/#HEAD/group/odb git_odb *odb; git_repository_odb(&odb, repo); // #### Raw Object Reading printf("\n*Raw Object Read*\n"); git_odb_object *obj; git_otype otype; const unsigned char *data; const char *str_type; int error; // We can read raw objects directly from the object database if we have the oid (SHA) // of the object. This allows us to access objects without knowing thier type and inspect // the raw bytes unparsed. error = git_odb_read(&obj, odb, &oid); // A raw object only has three properties - the type (commit, blob, tree or tag), the size // of the raw data and the raw, unparsed data itself. For a commit or tag, that raw data // is human readable plain ASCII text. For a blob it is just file contents, so it could be // text or binary data. For a tree it is a special binary format, so it's unlikely to be // hugely helpful as a raw object. data = (const unsigned char *)git_odb_object_data(obj); otype = git_odb_object_type(obj); // We provide methods to convert from the object type which is an enum, to a string // representation of that value (and vice-versa). str_type = git_object_type2string(otype); printf("object length and type: %d, %s\n", (int)git_odb_object_size(obj), str_type); // For proper memory management, close the object when you are done with it or it will leak // memory. git_odb_object_free(obj); // #### Raw Object Writing printf("\n*Raw Object Write*\n"); // You can also write raw object data to Git. This is pretty cool because it gives you // direct access to the key/value properties of Git. Here we'll write a new blob object // that just contains a simple string. Notice that we have to specify the object type as // the `git_otype` enum. git_odb_write(&oid, odb, "test data", sizeof("test data") - 1, GIT_OBJ_BLOB); // Now that we've written the object, we can check out what SHA1 was generated when the // object was written to our database. git_oid_fmt(out, &oid); printf("Written Object: %s\n", out); // ### Object Parsing // libgit2 has methods to parse every object type in Git so you don't have to work directly // with the raw data. This is much faster and simpler than trying to deal with the raw data // yourself. // #### Commit Parsing // [Parsing commit objects][pco] is simple and gives you access to all the data in the commit // - the // author (name, email, datetime), committer (same), tree, message, encoding and parent(s). // [pco]: http://libgit2.github.com/libgit2/#HEAD/group/commit printf("\n*Commit Parsing*\n"); git_commit *commit; git_oid_fromstr(&oid, "f0877d0b841d75172ec404fc9370173dfffc20d1"); error = git_commit_lookup(&commit, repo, &oid); const git_signature *author, *cmtter; const char *message; time_t ctime; unsigned int parents, p; // Each of the properties of the commit object are accessible via methods, including commonly // needed variations, such as `git_commit_time` which returns the author time and `_message` // which gives you the commit message. message = git_commit_message(commit); author = git_commit_author(commit); cmtter = git_commit_committer(commit); ctime = git_commit_time(commit); // The author and committer methods return [git_signature] structures, which give you name, email // and `when`, which is a `git_time` structure, giving you a timestamp and timezone offset. printf("Author: %s (%s)\n", author->name, author->email); // Commits can have zero or more parents. The first (root) commit will have no parents, most commits // will have one, which is the commit it was based on, and merge commits will have two or more. // Commits can technically have any number, though it's pretty rare to have more than two. parents = git_commit_parentcount(commit); for (p = 0;p < parents;p++) { git_commit *parent; git_commit_parent(&parent, commit, p); git_oid_fmt(out, git_commit_id(parent)); printf("Parent: %s\n", out); git_commit_free(parent); } // Don't forget to close the object to prevent memory leaks. You will have to do this for // all the objects you open and parse. git_commit_free(commit); // #### Writing Commits // // libgit2 provides a couple of methods to create commit objects easily as well. There are four // different create signatures, we'll just show one of them here. You can read about the other // ones in the [commit API docs][cd]. // [cd]: http://libgit2.github.com/libgit2/#HEAD/group/commit printf("\n*Commit Writing*\n"); git_oid tree_id, parent_id, commit_id; git_tree *tree; git_commit *parent; // Creating signatures for an authoring identity and time is pretty simple - you will need to have // this to create a commit in order to specify who created it and when. Default values for the name // and email should be found in the `user.name` and `user.email` configuration options. See the `config` // section of this example file to see how to access config values. git_signature_new((git_signature **)&author, "Scott Chacon", "*****@*****.**", 123456789, 60); git_signature_new((git_signature **)&cmtter, "Scott A Chacon", "*****@*****.**", 987654321, 90); // Commit objects need a tree to point to and optionally one or more parents. Here we're creating oid // objects to create the commit with, but you can also use git_oid_fromstr(&tree_id, "28873d96b4e8f4e33ea30f4c682fd325f7ba56ac"); git_tree_lookup(&tree, repo, &tree_id); git_oid_fromstr(&parent_id, "f0877d0b841d75172ec404fc9370173dfffc20d1"); git_commit_lookup(&parent, repo, &parent_id); // Here we actually create the commit object with a single call with all the values we need to create // the commit. The SHA key is written to the `commit_id` variable here. git_commit_create_v( &commit_id, /* out id */ repo, NULL, /* do not update the HEAD */ author, cmtter, NULL, /* use default message encoding */ "example commit", tree, 1, parent); // Now we can take a look at the commit SHA we've generated. git_oid_fmt(out, &commit_id); printf("New Commit: %s\n", out); // #### Tag Parsing // You can parse and create tags with the [tag management API][tm], which functions very similarly // to the commit lookup, parsing and creation methods, since the objects themselves are very similar. // [tm]: http://libgit2.github.com/libgit2/#HEAD/group/tag printf("\n*Tag Parsing*\n"); git_tag *tag; const char *tmessage, *tname; git_otype ttype; // We create an oid for the tag object if we know the SHA and look it up in the repository the same // way that we would a commit (or any other) object. git_oid_fromstr(&oid, "bc422d45275aca289c51d79830b45cecebff7c3a"); error = git_tag_lookup(&tag, repo, &oid); // Now that we have the tag object, we can extract the information it generally contains: the target // (usually a commit object), the type of the target object (usually 'commit'), the name ('v1.0'), // the tagger (a git_signature - name, email, timestamp), and the tag message. git_tag_target((git_object **)&commit, tag); tname = git_tag_name(tag); // "test" ttype = git_tag_type(tag); // GIT_OBJ_COMMIT (otype enum) tmessage = git_tag_message(tag); // "tag message\n" printf("Tag Message: %s\n", tmessage); git_commit_free(commit); // #### Tree Parsing // [Tree parsing][tp] is a bit different than the other objects, in that we have a subtype which is the // tree entry. This is not an actual object type in Git, but a useful structure for parsing and // traversing tree entries. // // [tp]: http://libgit2.github.com/libgit2/#HEAD/group/tree printf("\n*Tree Parsing*\n"); const git_tree_entry *entry; git_object *objt; // Create the oid and lookup the tree object just like the other objects. git_oid_fromstr(&oid, "2a741c18ac5ff082a7caaec6e74db3075a1906b5"); git_tree_lookup(&tree, repo, &oid); // Getting the count of entries in the tree so you can iterate over them if you want to. int cnt = git_tree_entrycount(tree); // 3 printf("tree entries: %d\n", cnt); entry = git_tree_entry_byindex(tree, 0); printf("Entry name: %s\n", git_tree_entry_name(entry)); // "hello.c" // You can also access tree entries by name if you know the name of the entry you're looking for. entry = git_tree_entry_byname(tree, "hello.c"); git_tree_entry_name(entry); // "hello.c" // Once you have the entry object, you can access the content or subtree (or commit, in the case // of submodules) that it points to. You can also get the mode if you want. git_tree_entry_to_object(&objt, repo, entry); // blob // Remember to close the looked-up object once you are done using it git_object_free(objt); // #### Blob Parsing // // The last object type is the simplest and requires the least parsing help. Blobs are just file // contents and can contain anything, there is no structure to it. The main advantage to using the // [simple blob api][ba] is that when you're creating blobs you don't have to calculate the size // of the content. There is also a helper for reading a file from disk and writing it to the db and // getting the oid back so you don't have to do all those steps yourself. // // [ba]: http://libgit2.github.com/libgit2/#HEAD/group/blob printf("\n*Blob Parsing*\n"); git_blob *blob; git_oid_fromstr(&oid, "af7574ea73f7b166f869ef1a39be126d9a186ae0"); git_blob_lookup(&blob, repo, &oid); // You can access a buffer with the raw contents of the blob directly. // Note that this buffer may not be contain ASCII data for certain blobs (e.g. binary files): // do not consider the buffer a NULL-terminated string, and use the `git_blob_rawsize` attribute to // find out its exact size in bytes printf("Blob Size: %ld\n", git_blob_rawsize(blob)); // 8 git_blob_rawcontent(blob); // "content" // ### Revwalking // // The libgit2 [revision walking api][rw] provides methods to traverse the directed graph created // by the parent pointers of the commit objects. Since all commits point back to the commit that // came directly before them, you can walk this parentage as a graph and find all the commits that // were ancestors of (reachable from) a given starting point. This can allow you to create `git log` // type functionality. // // [rw]: http://libgit2.github.com/libgit2/#HEAD/group/revwalk printf("\n*Revwalking*\n"); git_revwalk *walk; git_commit *wcommit; git_oid_fromstr(&oid, "f0877d0b841d75172ec404fc9370173dfffc20d1"); // To use the revwalker, create a new walker, tell it how you want to sort the output and then push // one or more starting points onto the walker. If you want to emulate the output of `git log` you // would push the SHA of the commit that HEAD points to into the walker and then start traversing them. // You can also 'hide' commits that you want to stop at or not see any of their ancestors. So if you // want to emulate `git log branch1..branch2`, you would push the oid of `branch2` and hide the oid // of `branch1`. git_revwalk_new(&walk, repo); git_revwalk_sorting(walk, GIT_SORT_TOPOLOGICAL | GIT_SORT_REVERSE); git_revwalk_push(walk, &oid); const git_signature *cauth; const char *cmsg; // Now that we have the starting point pushed onto the walker, we can start asking for ancestors. It // will return them in the sorting order we asked for as commit oids. // We can then lookup and parse the commited pointed at by the returned OID; // note that this operation is specially fast since the raw contents of the commit object will // be cached in memory while ((git_revwalk_next(&oid, walk)) == 0) { error = git_commit_lookup(&wcommit, repo, &oid); cmsg = git_commit_message(wcommit); cauth = git_commit_author(wcommit); printf("%s (%s)\n", cmsg, cauth->email); git_commit_free(wcommit); } // Like the other objects, be sure to free the revwalker when you're done to prevent memory leaks. // Also, make sure that the repository being walked it not deallocated while the walk is in // progress, or it will result in undefined behavior git_revwalk_free(walk); // ### Index File Manipulation // // The [index file API][gi] allows you to read, traverse, update and write the Git index file // (sometimes thought of as the staging area). // // [gi]: http://libgit2.github.com/libgit2/#HEAD/group/index printf("\n*Index Walking*\n"); git_index *index; unsigned int i, ecount; // You can either open the index from the standard location in an open repository, as we're doing // here, or you can open and manipulate any index file with `git_index_open_bare()`. The index // for the repository will be located and loaded from disk. git_repository_index(&index, repo); // For each entry in the index, you can get a bunch of information including the SHA (oid), path // and mode which map to the tree objects that are written out. It also has filesystem properties // to help determine what to inspect for changes (ctime, mtime, dev, ino, uid, gid, file_size and flags) // All these properties are exported publicly in the `git_index_entry` struct ecount = git_index_entrycount(index); for (i = 0; i < ecount; ++i) { git_index_entry *e = git_index_get(index, i); printf("path: %s\n", e->path); printf("mtime: %d\n", (int)e->mtime.seconds); printf("fs: %d\n", (int)e->file_size); } git_index_free(index); // ### References // // The [reference API][ref] allows you to list, resolve, create and update references such as // branches, tags and remote references (everything in the .git/refs directory). // // [ref]: http://libgit2.github.com/libgit2/#HEAD/group/reference printf("\n*Reference Listing*\n"); // Here we will implement something like `git for-each-ref` simply listing out all available // references and the object SHA they resolve to. git_strarray ref_list; git_reference_list(&ref_list, repo, GIT_REF_LISTALL); const char *refname; git_reference *ref; // Now that we have the list of reference names, we can lookup each ref one at a time and // resolve them to the SHA, then print both values out. for (i = 0; i < ref_list.count; ++i) { refname = ref_list.strings[i]; git_reference_lookup(&ref, repo, refname); switch (git_reference_type(ref)) { case GIT_REF_OID: git_oid_fmt(out, git_reference_oid(ref)); printf("%s [%s]\n", refname, out); break; case GIT_REF_SYMBOLIC: printf("%s => %s\n", refname, git_reference_target(ref)); break; default: fprintf(stderr, "Unexpected reference type\n"); exit(1); } } git_strarray_free(&ref_list); // ### Config Files // // The [config API][config] allows you to list and updatee config values in // any of the accessible config file locations (system, global, local). // // [config]: http://libgit2.github.com/libgit2/#HEAD/group/config printf("\n*Config Listing*\n"); const char *email; int32_t j; git_config *cfg; // Open a config object so we can read global values from it. git_config_open_ondisk(&cfg, "~/.gitconfig"); git_config_get_int32(cfg, "help.autocorrect", &j); printf("Autocorrect: %d\n", j); git_config_get_string(cfg, "user.email", &email); printf("Email: %s\n", email); // Finally, when you're done with the repository, you can free it as well. git_repository_free(repo); return 0; }
/* The wiki handler */ static int wiki_handler(request_rec *r) { wiki_conf *conf; git_repository *repo; const git_oid *tree_oid; char *path; const git_oid *oid; char hash[41]; hash[40] = '\0'; int ret; int type; MMIOT *doc; if (strcmp(r->handler, "wiki")) { return DECLINED; } if (r->header_only) { return OK; } conf = (wiki_conf *) ap_get_module_config(r->per_dir_config, &wiki_module); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "filename=%s", r->filename); if (conf->basepath) { path = ltrim(conf->basepath, r->parsed_uri.path); } else { path = r->parsed_uri.path + 1; } ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "path=%s", path); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "r->content_type=%s", r->content_type); if (conf->repo == NULL) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "WikiRepository is not set."); return HTTP_INTERNAL_SERVER_ERROR; } ret = git_repository_open(&repo, conf->repo); if (ret) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Cannot open git repository.(%s)", conf->repo); return HTTP_INTERNAL_SERVER_ERROR; } tree_oid = lookup_master_tree(repo); if (tree_oid == NULL) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Not found master tree."); git_repository_free(repo); } type = lookup_object_oid(r, repo, tree_oid, path, &oid); if (type == WIKI_NOTFOUND) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Object is not found."); git_repository_free(repo); return HTTP_NOT_FOUND; } else if(type == WIKI_DIR) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Directory listing is not implement yet."); git_repository_free(repo); return HTTP_FORBIDDEN; } else if(type == WIKI_ERROR) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Error at lookup."); git_repository_free(repo); return HTTP_NOT_FOUND; } git_oid_fmt(hash, oid); ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "object hash=%s", hash); const char *data; size_t size; git_odb *odb; ret = git_repository_odb(&odb, repo); git_odb_object *odb_object; ret = git_odb_read(&odb_object, odb, oid); data = git_odb_object_data(odb_object); size = git_odb_object_size(odb_object); git_odb_object_free(odb_object); // is this safe? if (type == WIKI_FOUND) { ap_rwrite(data, size, r); } else if(type == WIKI_MARKDOWN) { r->content_type = "text/html"; doc = mkd_string(data, size, 0); if (doc == NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mkd_string() returned NULL\n"); git_repository_free(repo); return HTTP_INTERNAL_SERVER_ERROR; } wiki_output(doc, r); mkd_cleanup(doc); } else { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Unknown Error.\n"); git_repository_free(repo); return HTTP_INTERNAL_SERVER_ERROR; } git_repository_free(repo); return OK; }
void test_refs_branches_upstreamname__initialize(void) { cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); git_buf_init(&upstream_name, 0); }
/* * If it's not a git repo, return NULL. Be very conservative. */ struct git_repository *is_git_repository(const char *filename, const char **branchp, const char **remote) { int flen, blen, ret; int offset = 1; struct stat st; git_repository *repo; char *loc, *branch; flen = strlen(filename); if (!flen || filename[--flen] != ']') return NULL; /* Find the matching '[' */ blen = 0; while (flen && filename[--flen] != '[') blen++; /* Ignore slashes at the end of the repo name */ while (flen && filename[flen-1] == '/') { flen--; offset++; } if (!flen) return NULL; /* * This is the "point of no return": the name matches * the git repository name rules, and we will no longer * return NULL. * * We will either return "dummy_git_repository" and the * branch pointer will have the _whole_ filename in it, * or we will return a real git repository with the * branch pointer being filled in with just the branch * name. * * The actual git reading/writing routines can use this * to generate proper error messages. */ *branchp = filename; loc = format_string("%.*s", flen, filename); if (!loc) return dummy_git_repository; branch = format_string("%.*s", blen, filename + flen + offset); if (!branch) { free(loc); return dummy_git_repository; } repo = is_remote_git_repository(loc, branch); if (repo) { if (remote) *remote = loc; else free(loc); *branchp = branch; return repo; } if (stat(loc, &st) < 0 || !S_ISDIR(st.st_mode)) { free(loc); free(branch); return dummy_git_repository; } ret = git_repository_open(&repo, loc); free(loc); if (ret < 0) { free(branch); return dummy_git_repository; } if (remote) *remote = NULL; *branchp = branch; return repo; }
static int handle(KDriver const *driver, KImplementation const *impl, int requested) { char const *url = k_dictionary_get(k_implementation_get_values(impl), "href"); char const *tag = k_dictionary_get(k_implementation_get_values(impl), "tag"); char const *path = k_dictionary_get(k_implementation_get_meta(impl), "name"); git_repository* repo = NULL; git_remote* origin = NULL; if (git_repository_open(&repo, path) == GIT_OK) { if (git_remote_load(&origin, repo, "origin") != GIT_OK) { git_repository_free(repo); return -1; } if (strcmp(url, git_remote_url(origin)) != 0) { giterr_set_str(GITERR_INVALID, "different origin"); git_repository_free(repo); return -1; } } else { if (git_repository_init(&repo, path, 0) != GIT_OK) { return -1; } if (git_remote_create(&origin, repo, "origin", url) != GIT_OK) { git_repository_free(repo); return -1; } } git_remote_set_update_fetchhead(origin, 0); git_remote_set_cred_acquire_cb(origin, cred_acquire, NULL); if (git_remote_connect(origin, GIT_DIRECTION_FETCH) != GIT_OK) { git_remote_free(origin); git_repository_free(repo); return -1; } if (git_remote_download(origin, transfer_progress, NULL) != GIT_OK) { git_remote_free(origin); git_repository_free(repo); return -1; } if (git_remote_update_tips(origin) != GIT_OK) { git_remote_free(origin); git_repository_free(repo); return -1; } git_object* object = NULL; if (git_revparse_single(&object, repo, tag) != GIT_OK) { git_remote_free(origin); git_repository_free(repo); return -1; } if (git_repository_set_head_detached(repo, git_object_id(object)) != GIT_OK) { git_object_free(object); git_remote_free(origin); git_repository_free(repo); return -1; } git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; checkout_opts.version = GIT_CHECKOUT_OPTS_VERSION; checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; checkout_opts.progress_cb = checkout_progress; checkout_opts.progress_payload = NULL; if (git_checkout_tree(repo, object, &checkout_opts) != GIT_OK) { git_object_free(object); git_remote_free(origin); git_repository_free(repo); return -1; } git_object_free(object); git_remote_free(origin); git_repository_free(repo); return 0; }
int main() { git_repository* repo; git_repository_open(&repo, "."); return diff(repo); }
void test_revwalk_mergebase__initialize(void) { cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); cl_git_pass(git_repository_open(&_repo2, cl_fixture("twowaymerge.git"))); }
int cmd_checkout(int argc, const char **argv) { /* Delete the following line once gits tests pass please_git_do_it_for_me(); if (argc != 1) please_git_do_it_for_me(); */ git_index *index; git_repository *repo; git_index_entry *index_entry; git_oid id; /* Open the repository */ if (git_repository_open(&repo, ".git")) { libgit_error(); } /* Get the Index file of a Git repository */ if (git_repository_index(&index,repo)) { libgit_error(); } /* Find the first index of any entries which point to given path in the Git index */ if (git_index_find (index, ".git")) { libgit_error(); } int i = 0; /* get a pointer to one of the entries in the index */ index_entry = git_index_get(index, i); if (index_entry == NULL) printf("Out of bound"); else id = index_entry->oid; (void)id; git_reference *symbolic_ref; if (git_reference_lookup(&symbolic_ref, repo, "HEAD")) libgit_error(); git_reference *direct_ref; if (git_reference_resolve(&direct_ref, symbolic_ref)) libgit_error(); const git_oid *oid; oid = git_reference_oid(direct_ref); if (oid == NULL) { printf("Internal error: reference is not direct\n"); return EXIT_FAILURE; } git_tree *tree; /* Lookup a tree object from the repository */ if (git_tree_lookup(&tree, repo, oid)) libgit_error(); /* Update the index ?? */ if (git_index_read(index)) libgit_error(); git_index_free(index); git_tree_close(tree); return EXIT_SUCCESS; }
void test_refs_iterator__initialize(void) { cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); }
void QGit::stageFiles(QStringList items) { git_repository *repo = nullptr; git_index *index = nullptr; int res = 0; QGitError error; try { if (items.count() == 0) { throw QGitError(); } res = git_repository_open(&repo, m_path.absolutePath().toUtf8().constData()); if (res) { throw QGitError("git_repository_open", res); } res = git_repository_index(&index, repo); if (res) { throw QGitError("git_repository_index", res); } for(const auto &item: items) { res = git_index_add_bypath(index, item.toUtf8().constData()); if (res == GIT_ENOTFOUND) { // FIXME: Properly implement stage add/delete files. res = git_index_remove_bypath(index, item.toUtf8().constData()); if (res) { throw QGitError("git_index_remove_bypath", res); } } if (res) { throw QGitError("git_index_add_bypath", res); } } res = git_index_write(index); if (res) { throw QGitError("git_index_write", res); } } catch(const QGitError &ex) { error = ex; } emit stageFilesReply(error); if (index) { git_index_free(index); index = nullptr; } if (repo) { git_repository_free(repo); repo = nullptr; } }
void QGit::commitDiffContent(QString first, QString second, QList<QString> files) { git_commit *first_commit = nullptr, *second_commit = nullptr; git_object *first_obj = nullptr, *second_obj = nullptr; git_tree *first_tree = nullptr, *second_tree = nullptr; const git_diff_delta *delta = nullptr; git_repository *repo = nullptr; git_patch *patch = nullptr; QList<QGitDiffFile> items; git_diff *diff = nullptr; QGitError error; int res = 0; try { res = git_repository_open(&repo, m_path.absolutePath().toUtf8().constData()); if (res) { throw QGitError("git_repository_open", res); } if (!first.isEmpty()) { res = git_revparse_single(&first_obj, repo, first.toLatin1()); if (res) { throw QGitError("git_revparse_single(first)", res); } res = git_commit_lookup(&first_commit, repo, git_object_id(first_obj)); if (res) { throw QGitError("git_commit_lookup(first)", res); } res = git_commit_tree(&first_tree, first_commit); if (res) { throw QGitError("git_commit_tree(first)", res); } } if (second == "staged") { git_diff_options options; res = git_revparse_single(&first_obj, repo, "HEAD^{tree}"); if (res) { throw QGitError("git_revparse_single(staged)", res); } res = git_tree_lookup(&first_tree, repo, git_object_id(first_obj)); if (res) { throw QGitError("git_tree_lookup(staged)", res); } memset(&options, 0, sizeof(options)); options.version = GIT_DIFF_OPTIONS_VERSION; options.flags = GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT; options.context_lines = 3; res = git_diff_tree_to_index(&diff, repo, first_tree, nullptr, &options); if (res) { throw QGitError("git_diff_tree_to_index(staged)", res); } } else if (second == "unstaged") { git_diff_options options; memset(&options, 0, sizeof(options)); options.version = GIT_DIFF_OPTIONS_VERSION; options.flags = GIT_DIFF_INCLUDE_UNTRACKED | GIT_DIFF_SHOW_UNTRACKED_CONTENT; options.context_lines = 3; res = git_diff_index_to_workdir(&diff, repo, nullptr, &options); if (res) { throw QGitError("git_diff_index_to_workdir", res); } } else { res = git_revparse_single(&second_obj, repo, second.toLatin1()); if (res) { throw QGitError("git_revparse_single(second)", res); } res = git_commit_lookup(&second_commit, repo, git_object_id(second_obj)); if (res) { throw QGitError("git_commit_lookup(second)", res); } res = git_commit_tree(&second_tree, second_commit); if (res) { throw QGitError("git_commit_tree(second)", res); } res = git_diff_tree_to_tree(&diff, repo, first_tree, second_tree, nullptr); if (res) { throw QGitError("git_diff_tree_to_tree", res); } } size_t _count = git_diff_num_deltas(diff); for(size_t c = 0; c < _count; c++) { delta = git_diff_get_delta(diff, c); QGitDiffFile item(delta); if (files.contains(item.new_file().path())) { res = git_patch_from_diff(&patch, diff, c); if (res) { throw QGitError("git_patch_from_diff", res); } size_t hunks = git_patch_num_hunks(patch); for(size_t hunk_cnt = 0; hunk_cnt < hunks; hunk_cnt++) { const git_diff_hunk *hunk = nullptr; res = git_patch_get_hunk(&hunk, nullptr, patch, hunk_cnt); if (res) { throw QGitError("git_patch_get_hunk", res); } QGitDiffHunk hunkObj(hunk); const git_diff_line *line = nullptr; int lines = git_patch_num_lines_in_hunk(patch, hunk_cnt); if (lines > 0) { for(int line_cnt = 0; line_cnt < lines; line_cnt++) { res = git_patch_get_line_in_hunk(&line, patch, hunk_cnt, static_cast<size_t>(line_cnt)); if (res) { throw QGitError("git_patch_get_line_in_hunk", res); } hunkObj.addLine(line); } } item.addHunk(hunkObj); } items.append(item); } } } catch(const QGitError &ex) { error = ex; } emit commitDiffContentReply(first, second, items, error); }
void QGit::commitDiff(QString commitId) { const git_diff_delta *delta = nullptr; git_tree *commit_tree = nullptr; git_tree *parent_tree = nullptr; git_repository *repo = nullptr; git_commit *parent = nullptr; git_commit *commit = nullptr; git_object *obj = nullptr; git_diff *diff = nullptr; QList<QGitCommitDiffParent> parents; QGitSignature commitAuthor, commitCommiter; QDateTime commitTime; QString commitMessage; QGitCommit commitDiff; unsigned int parentCount; int res = 0; QGitError error; try { res = git_repository_open(&repo, m_path.absolutePath().toUtf8().constData()); if (res) { throw QGitError("git_repository_open", res); } if (commitId.isEmpty()) { commitId = QStringLiteral("HEAD"); } res = git_revparse_single(&obj, repo, commitId.toLatin1()); if (res) { throw QGitError("git_revparse_single", res); } res = git_commit_lookup(&commit, repo, git_object_id(obj)); if (res) { throw QGitError("git_commit_lookup", res); } res = git_commit_tree(&commit_tree, commit); if (res) { throw QGitError("git_commit_tree", res); } commitAuthor = QGitSignature(QString::fromUtf8(git_commit_author(commit)->name), QString::fromUtf8(git_commit_author(commit)->email), QDateTime::fromMSecsSinceEpoch(git_commit_author(commit)->when.time * 1000)); commitCommiter = QGitSignature(QString::fromUtf8(git_commit_committer(commit)->name), QString::fromUtf8(git_commit_committer(commit)->email), QDateTime::fromMSecsSinceEpoch(git_commit_committer(commit)->when.time * 1000)); auto time = git_commit_time(commit); auto timeOffset = git_commit_time_offset(commit); commitTime = QDateTime::fromMSecsSinceEpoch(time * 1000); commitTime.setOffsetFromUtc(timeOffset * 60); commitMessage = QString::fromUtf8(git_commit_message(commit)); parentCount = git_commit_parentcount(commit); if (parentCount == 0) { QGitCommitDiffParent item; res = git_diff_tree_to_tree(&diff, repo, nullptr, commit_tree, nullptr); if (res) { throw QGitError("git_diff_tree_to_tree", res); } size_t _count = git_diff_num_deltas(diff); for(size_t c = 0; c < _count; c++) { delta = git_diff_get_delta(diff, c); item.addFile(delta); } git_diff_free(diff); diff = nullptr; parents.append(item); } else { for(unsigned int c = 0; c < parentCount; c++) { res = git_commit_parent(&parent, commit, c); if (res) { throw QGitError("git_commit_parent", res); } char commit_id[41] = {0, }; const git_oid *oid = git_commit_id(parent); git_oid_tostr(commit_id, 41, oid); QGitCommitDiffParent item(commit_id); res = git_commit_tree(&parent_tree, parent); if (res) { throw QGitError("git_commit_tree", res); } res = git_diff_tree_to_tree(&diff, repo, parent_tree, commit_tree, nullptr); if (res) { throw QGitError("git_diff_tree_to_tree", res); } size_t _count = git_diff_num_deltas(diff); for(size_t c = 0; c < _count; c++) { delta = git_diff_get_delta(diff, c); item.addFile(delta); } git_diff_free(diff); diff = nullptr; git_tree_free(parent_tree); parent_tree = nullptr; git_commit_free(parent); parent = nullptr; parents.append(item); } } } catch(const QGitError &ex) { error = ex; } commitDiff = QGitCommit(commitId, parents, commitTime, commitAuthor, commitCommiter, commitMessage); emit commitDiffReply(commitId, commitDiff, error); if (diff) { git_diff_free(diff); diff = nullptr; } if (parent_tree) { git_tree_free(parent_tree); parent_tree = nullptr; } if (parent) { git_commit_free(parent); parent = nullptr; } if (commit_tree) { git_tree_free(commit_tree); commit_tree = nullptr; } if(commit) { git_commit_free(commit); commit = nullptr; } if(obj) { git_object_free(obj); obj = nullptr; } if (repo) { git_repository_free(repo); repo = nullptr; } }
void test_object_shortid__initialize(void) { cl_git_pass(git_repository_open(&_repo, cl_fixture("duplicate.git"))); }
void download(KImplementation const *impl, int requested, KError *error, void *ctx) { KDictionary const *values = k_implementation_get_values(impl); char const *href = k_dictionary_lookup(values, "href"); char const *tag = k_dictionary_lookup(values, "tag"); char const *path = k_implementation_get_name(impl); git_repository *repo = NULL; git_remote *origin = NULL; git_object *object = NULL; struct progress_data progress_data = {{0}}; git_checkout_opts checkout_opts = GIT_CHECKOUT_OPTS_INIT; checkout_opts.version = GIT_CHECKOUT_OPTS_VERSION; checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; checkout_opts.progress_cb = checkout_progress; checkout_opts.progress_payload = &progress_data; if (git_repository_open(&repo, path) == GIT_OK) { if (git_remote_load(&origin, repo, "origin") != GIT_OK) { k_error_set(error, giterr_last()->message); goto repository_free; } if (strcmp(git_remote_url(origin), href) != 0) { k_error_set(error, "different origin"); goto remote_free; } } else { if (git_repository_init(&repo, path, 0) != GIT_OK) { k_error_set(error, giterr_last()->message); return; } if (git_remote_create(&origin, repo, "origin", href) != GIT_OK) { k_error_set(error, giterr_last()->message); goto repository_free; } } git_remote_set_update_fetchhead(origin, 0); git_remote_set_cred_acquire_cb(origin, cred_acquire, NULL); if (git_remote_connect(origin, GIT_DIRECTION_FETCH) != GIT_OK) { k_error_set(error, giterr_last()->message); goto remote_free; } if (git_remote_download(origin, fetch_progress, &progress_data) != GIT_OK) { k_error_set(error, giterr_last()->message); goto remote_disconnect; } if (git_remote_update_tips(origin) != GIT_OK) { k_error_set(error, giterr_last()->message); goto remote_disconnect; } if (git_revparse_single(&object, repo, tag) != GIT_OK) { k_error_set(error, giterr_last()->message); goto remote_disconnect; } if (git_repository_set_head_detached(repo, git_object_id(object)) != GIT_OK) { k_error_set(error, giterr_last()->message); goto remote_disconnect; } if (git_checkout_tree(repo, object, &checkout_opts) != GIT_OK) { k_error_set(error, giterr_last()->message); } remote_disconnect: git_remote_disconnect(origin); remote_free: git_remote_free(origin); repository_free: git_repository_free(repo); }
void test_revwalk_basic__initialize(void) { cl_git_pass(git_repository_open(&_repo, cl_fixture("testrepo.git"))); cl_git_pass(git_revwalk_new(&_walk, _repo)); }
void GitRepository::open() { git_repository* repo = NULL; git_eval(git_repository_open(&repo, m_local_dir_path.absolutePath().toLocal8Bit())); setRepository(repo); }
int main() { git_libgit2_init(); git_repository* rep = nullptr; git_rebase* prebase = nullptr; git_rebase_options rebase_opt = GIT_REBASE_OPTIONS_INIT; git_reference* onto_branch = nullptr; git_annotated_commit* onto = nullptr; git_rebase_operation* operation = nullptr; size_t entrycount; size_t current; git_signature* me = nullptr; git_index* index = nullptr; git_oid new_commit; int error = 0; // git open git_repository_open(&rep, path); error = git_rebase_open(&prebase, rep, &rebase_opt); // There is no rebase in progress if (error == GIT_ENOTFOUND) { git_branch_lookup(&onto_branch, rep, "new", GIT_BRANCH_LOCAL); git_annotated_commit_from_ref(&onto, rep, onto_branch); git_rebase_init(&prebase, rep, nullptr /* current branch */, nullptr /* upstream */ , onto /* branch to rebase onto */, &rebase_opt); } else if (error < 0) { const git_error *e = giterr_last(); std::cout << "Error: " << error << " / " << e->klass << " : " << e->message << std::endl; goto SHUTDOWN; } entrycount = git_rebase_operation_entrycount(prebase); std::cout<< "rebase entry count: " << entrycount << "\n"; while (git_rebase_next(&operation, prebase) != GIT_ITEROVER) { current = git_rebase_operation_current(prebase); // (called `init` but not yet `next`) then this returns `GIT_REBASE_NO_OPERATION` std::cout<< "rebase current index: " << current << "\n"; if (GIT_REBASE_NO_OPERATION == current) { std::cout<< "rebase no operation" << "\n"; } operation = git_rebase_operation_byindex(prebase, 0); } // reslove conflicts git_repository_index(&index, rep); if (git_index_has_conflicts(index)) { // git checkout --theirs git_checkout_options opt = GIT_CHECKOUT_OPTIONS_INIT; opt.checkout_strategy |= GIT_CHECKOUT_USE_THEIRS; git_checkout_index(rep, index, &opt); } // add git_index_update_all(index, nullptr, nullptr, nullptr); git_index_write(index); // commit git_signature_now(&me, "XiaochenFTX", "*****@*****.**"); git_rebase_commit(&new_commit, prebase, me, me, "UTF-8", "new rebase"); error = git_rebase_finish(prebase, me); if (error < 0) { const git_error *e = giterr_last(); std::cout << "Error: " << error << " / " << e->klass << " : " << e->message << std::endl; goto SHUTDOWN; } // git_rebase_abort(prebase); git_rebase_free(prebase); SHUTDOWN: git_repository_free(rep); git_libgit2_shutdown(); return 0; }
bool Masterlist::Update(const boost::filesystem::path& path, const std::string& repoUrl, const std::string& repoBranch) { GitHelper git; fs::path repoPath = path.parent_path(); string filename = path.filename().string(); if (repoUrl.empty() || repoBranch.empty()) throw std::invalid_argument("Repository URL and branch must not be empty."); // Initialise checkout options. BOOST_LOG_TRIVIAL(debug) << "Setting up checkout options."; char * paths = new char[filename.length() + 1]; strcpy(paths, filename.c_str()); git.GetData().checkout_options.checkout_strategy = GIT_CHECKOUT_FORCE | GIT_CHECKOUT_DONT_REMOVE_EXISTING; git.GetData().checkout_options.paths.strings = &paths; git.GetData().checkout_options.paths.count = 1; // Initialise clone options. git.GetData().clone_options.checkout_opts = git.GetData().checkout_options; git.GetData().clone_options.bare = 0; git.GetData().clone_options.checkout_branch = repoBranch.c_str(); // Now try to access the repository if it exists, or clone one if it doesn't. BOOST_LOG_TRIVIAL(trace) << "Attempting to open the Git repository at: " << repoPath; if (!git.IsRepository(repoPath)) git.Clone(repoPath, repoUrl); else { // Repository exists: check settings are correct, then pull updates. git.SetErrorMessage((boost::format(translate("An error occurred while trying to access the local masterlist repository. If this error happens again, try deleting the \".git\" folder in %1%.")) % repoPath.string()).str()); // Open the repository. BOOST_LOG_TRIVIAL(info) << "Existing repository found, attempting to open it."; git.Call(git_repository_open(&git.GetData().repo, repoPath.string().c_str())); // Set the remote URL. BOOST_LOG_TRIVIAL(info) << "Using remote URL: " << repoUrl; git.Call(git_remote_set_url(git.GetData().repo, "origin", repoUrl.c_str())); // Now fetch updates from the remote. git.Fetch("origin"); // Check that a local branch with the correct name exists. git.SetErrorMessage((boost::format(translate("An error occurred while trying to access the local masterlist repository. If this error happens again, try deleting the \".git\" folder in %1%.")) % repoPath.string()).str()); int ret = git_branch_lookup(&git.GetData().reference, git.GetData().repo, repoBranch.c_str(), GIT_BRANCH_LOCAL); if (ret == GIT_ENOTFOUND) // Branch doesn't exist. Create a new branch using the remote branch's latest commit. git.CheckoutNewBranch("origin", repoBranch); else { // The local branch exists. Need to merge the remote branch // into it. git.Call(ret); // Handle other errors from preceding branch lookup. // Check if HEAD points to the desired branch and set it to if not. if (!git_branch_is_head(git.GetData().reference)) { BOOST_LOG_TRIVIAL(trace) << "Setting HEAD to follow branch: " << repoBranch; git.Call(git_repository_set_head(git.GetData().repo, (string("refs/heads/") + repoBranch).c_str())); } // Get remote branch reference. git.Call(git_branch_upstream(&git.GetData().reference2, git.GetData().reference)); BOOST_LOG_TRIVIAL(trace) << "Checking HEAD and remote branch's mergeability."; git_merge_analysis_t analysis; git_merge_preference_t pref; git.Call(git_annotated_commit_from_ref(&git.GetData().annotated_commit, git.GetData().repo, git.GetData().reference2)); git.Call(git_merge_analysis(&analysis, &pref, git.GetData().repo, (const git_annotated_commit **)&git.GetData().annotated_commit, 1)); if ((analysis & GIT_MERGE_ANALYSIS_FASTFORWARD) == 0 && (analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE) == 0) { // The local branch can't be easily merged. Best just to delete and recreate it. BOOST_LOG_TRIVIAL(trace) << "Local branch cannot be easily merged with remote branch."; BOOST_LOG_TRIVIAL(trace) << "Deleting the local branch."; git.Call(git_branch_delete(git.GetData().reference)); // Need to free ref before calling git.CheckoutNewBranch() git_reference_free(git.GetData().reference); git.GetData().reference = nullptr; git_reference_free(git.GetData().reference2); git.GetData().reference2 = nullptr; git.CheckoutNewBranch("origin", repoBranch); } else { // Get remote branch commit ID. git.Call(git_reference_peel(&git.GetData().object, git.GetData().reference2, GIT_OBJ_COMMIT)); const git_oid * remote_commit_id = git_object_id(git.GetData().object); git_object_free(git.GetData().object); git.GetData().object = nullptr; git_reference_free(git.GetData().reference2); git.GetData().reference2 = nullptr; bool updateBranchHead = true; if ((analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE) != 0) { // No merge is required, but HEAD might be ahead of the remote branch. Check // to see if that's the case, and move HEAD back to match the remote branch // if so. BOOST_LOG_TRIVIAL(trace) << "Local branch is up-to-date with remote branch."; BOOST_LOG_TRIVIAL(trace) << "Checking to see if local and remote branch heads are equal."; // Get local branch commit ID. git.Call(git_reference_peel(&git.GetData().object, git.GetData().reference, GIT_OBJ_COMMIT)); const git_oid * local_commit_id = git_object_id(git.GetData().object); git_object_free(git.GetData().object); git.GetData().object = nullptr; updateBranchHead = local_commit_id->id != remote_commit_id->id; // If the masterlist in // HEAD also matches the masterlist file, no further // action needs to be taken. Otherwise, a checkout // must be performed and the checked-out file parsed. if (!updateBranchHead) { BOOST_LOG_TRIVIAL(trace) << "Local and remote branch heads are equal."; if (!GitHelper::IsFileDifferent(repoPath, filename)) { BOOST_LOG_TRIVIAL(info) << "Local branch and masterlist file are already up to date."; return false; } } else BOOST_LOG_TRIVIAL(trace) << "Local branch heads is ahead of remote branch head."; } else BOOST_LOG_TRIVIAL(trace) << "Local branch can be fast-forwarded to remote branch."; if (updateBranchHead) { // The remote branch reference points to a particular // commit. Update the local branch reference to point // to the same commit. BOOST_LOG_TRIVIAL(trace) << "Syncing local branch head with remote branch head."; git.Call(git_reference_set_target(&git.GetData().reference2, git.GetData().reference, remote_commit_id, "Setting branch reference.")); git_reference_free(git.GetData().reference2); git.GetData().reference2 = nullptr; } git_reference_free(git.GetData().reference); git.GetData().reference = nullptr; BOOST_LOG_TRIVIAL(trace) << "Performing a Git checkout of HEAD."; git.Call(git_checkout_head(git.GetData().repo, &git.GetData().checkout_options)); } } } // Now whether the repository was cloned or updated, the working directory contains // the latest masterlist. Try parsing it: on failure, detach the HEAD back one commit // and try again. bool parsingFailed = false; std::string parsingError; git.SetErrorMessage((boost::format(translate("An error occurred while trying to read information on the updated masterlist. If this error happens again, try deleting the \".git\" folder in %1%.")) % repoPath.string()).str()); do { // Get the HEAD revision's short ID. string revision = git.GetHeadShortId(); //Now try parsing the masterlist. BOOST_LOG_TRIVIAL(debug) << "Testing masterlist parsing."; try { this->Load(path); parsingFailed = false; } catch (std::exception& e) { parsingFailed = true; if (parsingError.empty()) parsingError = boost::locale::translate("Masterlist revision").str() + " " + string(revision) + ": " + e.what() + ". " + boost::locale::translate("The latest masterlist revision contains a syntax error, LOOT is using the most recent valid revision instead. Syntax errors are usually minor and fixed within hours.").str(); //There was an error, roll back one revision. BOOST_LOG_TRIVIAL(error) << "Masterlist parsing failed. Masterlist revision " + string(revision) + ": " + e.what(); git.CheckoutRevision("HEAD^"); } } while (parsingFailed); if (!parsingError.empty()) AppendMessage(Message(MessageType::error, parsingError)); return true; }
void SyncState::sync() { m_timer.restart(); // Set up directory structure, if necessary std::string tmpPath = cpp3ds::FileSystem::getFilePath("sdmc:/3ds/BrewMan/tmp"); std::string cachePath = cpp3ds::FileSystem::getFilePath("sdmc:/3ds/BrewMan/cache"); std::string installedPath = cpp3ds::FileSystem::getFilePath("sdmc:/3ds/BrewMan/installed"); if (pathExists(tmpPath.c_str(), false)) removeDirectory(tmpPath.c_str()); mkdir(tmpPath.c_str(), 0777); if (!pathExists(cachePath.c_str(), false)) mkdir(cachePath.c_str(), 0777); if (!pathExists(installedPath.c_str(), false)) mkdir(installedPath.c_str(), 0777); // If auto-dated, boot into newest BrewMan if (autoUpdate()) { char buf[256]; size_t len; FILE *src = fopen("sdmc:/3ds/BrewMan/tmp/update.3dsx", "rb"); FILE *dst = fopen("sdmc:/3ds/BrewMan/tmp/update-copy.3dsx", "wb"); while ((len = fread(buf, 1, sizeof(buf), src)) > 0) fwrite(buf, 1, sizeof(buf), dst); fclose(src); fclose(dst); bootApp("/3ds/BrewMan/tmp/update.3dsx", ""); requestStackClear(); return; } git_repository *repo = NULL; const char *repoUrl = "git://github.com/Repo3DS/ideal-enigma.git"; const std::string path = cpp3ds::FileSystem::getFilePath(REPO_DIR); git_clone_options opts = GIT_CLONE_OPTIONS_INIT; setStatus("Fetching git repo..."); int error = git_clone(&repo, repoUrl, path.c_str(), NULL); if (error < 0) { if (error == GIT_EEXISTS) { error = git_repository_open(&repo, path.c_str()); if (error == 0) { git_remote *remote; error = git_remote_lookup(&remote, repo, "origin"); if (error == 0) { error = git_remote_fetch(remote, NULL, NULL, "pull"); if (error == 0) { git_annotated_commit *our_head, *their_heads[1]; if (git_repository_fetchhead_foreach(repo, find_master, NULL) == 0) { git_annotated_commit_from_fetchhead(&their_heads[0], repo, "master", repoUrl, &m_git_oid); git_merge_analysis_t analysis; git_merge_preference_t prefs; git_merge_analysis(&analysis, &prefs, repo, (const git_annotated_commit**)their_heads, 1); if (analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE) printf("up to date\n"); else if (analysis & GIT_MERGE_ANALYSIS_FASTFORWARD) { printf("fast-forwarding\n"); // if (git_merge(repo, (const git_annotated_commit **)their_heads, 1, NULL, NULL) == 0) { git_reference *ref; git_reference *newref; if (git_reference_lookup(&ref, repo, "refs/heads/master") == 0) git_reference_set_target(&newref, ref, &m_git_oid, "BrewMan pull: Fast-forward"); git_reset_from_annotated(repo, their_heads[0], GIT_RESET_HARD, NULL); git_reference_free(ref); git_repository_state_cleanup(repo); } git_annotated_commit_free(their_heads[0]); } } } } git_repository_free(repo); const git_error *e = giterr_last(); if (e) { setStatus(_("Error %d/%d\n%s\nCloning repo again...", error, e->klass, e->message)); if (!removeDirectory(path.c_str())) { cpp3ds::sleep(cpp3ds::seconds(2.f)); sync(); } else { setStatus("Repo failure. Please report this error.\nAnd delete /3ds/BrewMan/repo/ and try again."); } return; } } const git_error *e = giterr_last(); if (e) { setStatus(_("Error %d/%d: %s", error, e->klass, e->message)); return; } } setStatus("Everything up-to-date!"); // Give the Title animation time to finish if necessary while (m_timer.getElapsedTime() < cpp3ds::seconds(5.f)) cpp3ds::sleep(cpp3ds::milliseconds(50)); requestStackClear(); requestStackPush(States::Browse); }
struct status_entry_counts *counts = (struct status_entry_counts *)payload; counts->entry_count++; if (status_flags != expected_status_flags) counts->wrong_status_flags_count++; return GIT_SUCCESS; } BEGIN_TEST(statuscb0, "test retrieving status for worktree of repository") git_repository *repo; struct status_entry_counts counts; must_pass(copydir_recurs(STATUS_WORKDIR_FOLDER, TEMP_REPO_FOLDER)); must_pass(git_futils_mv_atomic(STATUS_REPOSITORY_TEMP_FOLDER, TEST_STD_REPO_FOLDER)); must_pass(git_repository_open(&repo, TEST_STD_REPO_FOLDER)); memset(&counts, 0x0, sizeof(struct status_entry_counts)); git_status_foreach(repo, status_cb, &counts); must_be_true(counts.entry_count == ENTRY_COUNT); must_be_true(counts.wrong_status_flags_count == 0); git_repository_free(repo); git_futils_rmdir_r(TEMP_REPO_FOLDER, 1); END_TEST BEGIN_TEST(singlestatus0, "test retrieving status for single file") git_repository *repo; unsigned int status_flags; int i;
void test_refs_branches_ishead__initialize(void) { cl_git_pass(git_repository_open(&repo, cl_fixture("testrepo.git"))); }
} for (i = 0; i < results_count; ++i) if (memcmp(possible_results[i], result_array, result_bytes) == 0) return GIT_SUCCESS; return GIT_ERROR; } BEGIN_TEST(walk0, "do a simple walk on a repo with different sorting modes") git_oid id; git_repository *repo; git_revwalk *walk; must_pass(git_repository_open(&repo, REPOSITORY_FOLDER)); must_pass(git_revwalk_new(&walk, repo)); git_oid_mkstr(&id, commit_head); must_pass(test_walk(walk, &id, GIT_SORT_TIME, commit_sorting_time, 1)); must_pass(test_walk(walk, &id, GIT_SORT_TOPOLOGICAL, commit_sorting_topo, 2)); must_pass(test_walk(walk, &id, GIT_SORT_TIME | GIT_SORT_REVERSE, commit_sorting_time_reverse, 1)); must_pass(test_walk(walk, &id, GIT_SORT_TOPOLOGICAL | GIT_SORT_REVERSE, commit_sorting_topo_reverse, 2)); git_revwalk_free(walk); git_repository_free(repo); END_TEST BEGIN_SUITE(revwalk) ADD_TEST(walk0);
void test_object_peel__initialize(void) { cl_git_pass(git_repository_open(&g_repo, cl_fixture("testrepo.git"))); }
void test_submodule_modify__edit_and_save(void) { git_submodule *sm1, *sm2; char *old_url; git_submodule_ignore_t old_ignore; git_submodule_update_t old_update; git_repository *r2; int old_fetchrecurse; cl_git_pass(git_submodule_lookup(&sm1, g_repo, "sm_changed_head")); old_url = git__strdup(git_submodule_url(sm1)); /* modify properties of submodule */ cl_git_pass(git_submodule_set_url(sm1, SM_LIBGIT2_URL)); old_ignore = git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_UNTRACKED); old_update = git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_REBASE); old_fetchrecurse = git_submodule_set_fetch_recurse_submodules(sm1, 1); cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm1)); cl_assert_equal_i( (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm1)); cl_assert_equal_i( (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm1)); cl_assert_equal_i(1, git_submodule_fetch_recurse_submodules(sm1)); /* revert without saving (and confirm setters return old value) */ cl_git_pass(git_submodule_set_url(sm1, old_url)); cl_assert_equal_i( (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_DEFAULT)); cl_assert_equal_i( (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_DEFAULT)); cl_assert_equal_i( 1, git_submodule_set_fetch_recurse_submodules(sm1, old_fetchrecurse)); /* check that revert was successful */ cl_assert_equal_s(old_url, git_submodule_url(sm1)); cl_assert_equal_i((int)old_ignore, (int)git_submodule_ignore(sm1)); cl_assert_equal_i((int)old_update, (int)git_submodule_update(sm1)); cl_assert_equal_i( old_fetchrecurse, git_submodule_fetch_recurse_submodules(sm1)); /* modify properties of submodule (again) */ cl_git_pass(git_submodule_set_url(sm1, SM_LIBGIT2_URL)); git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_UNTRACKED); git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_REBASE); git_submodule_set_fetch_recurse_submodules(sm1, 1); /* call save */ cl_git_pass(git_submodule_save(sm1)); /* attempt to "revert" values */ git_submodule_set_ignore(sm1, GIT_SUBMODULE_IGNORE_DEFAULT); git_submodule_set_update(sm1, GIT_SUBMODULE_UPDATE_DEFAULT); /* but ignore and update should NOT revert because the DEFAULT * should now be the newly saved value... */ cl_assert_equal_i( (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm1)); cl_assert_equal_i( (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm1)); cl_assert_equal_i(1, git_submodule_fetch_recurse_submodules(sm1)); /* call reload and check that the new values are loaded */ cl_git_pass(git_submodule_reload(sm1)); cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm1)); cl_assert_equal_i( (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm1)); cl_assert_equal_i( (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm1)); cl_assert_equal_i(1, git_submodule_fetch_recurse_submodules(sm1)); /* open a second copy of the repo and compare submodule */ cl_git_pass(git_repository_open(&r2, "submod2")); cl_git_pass(git_submodule_lookup(&sm2, r2, "sm_changed_head")); cl_assert_equal_s(SM_LIBGIT2_URL, git_submodule_url(sm2)); cl_assert_equal_i( (int)GIT_SUBMODULE_IGNORE_UNTRACKED, (int)git_submodule_ignore(sm2)); cl_assert_equal_i( (int)GIT_SUBMODULE_UPDATE_REBASE, (int)git_submodule_update(sm2)); cl_assert_equal_i(1, git_submodule_fetch_recurse_submodules(sm2)); git_repository_free(r2); git__free(old_url); }
static int clone_local_into(git_repository *repo, git_remote *remote, const git_fetch_options *fetch_opts, const git_checkout_options *co_opts, const char *branch, int link) { int error, flags; git_repository *src; git_buf src_odb = GIT_BUF_INIT, dst_odb = GIT_BUF_INIT, src_path = GIT_BUF_INIT; git_buf reflog_message = GIT_BUF_INIT; assert(repo && remote); if (!git_repository_is_empty(repo)) { git_error_set(GIT_ERROR_INVALID, "the repository is not empty"); return -1; } /* * Let's figure out what path we should use for the source * repo, if it's not rooted, the path should be relative to * the repository's worktree/gitdir. */ if ((error = git_path_from_url_or_path(&src_path, git_remote_url(remote))) < 0) return error; /* Copy .git/objects/ from the source to the target */ if ((error = git_repository_open(&src, git_buf_cstr(&src_path))) < 0) { git_buf_dispose(&src_path); return error; } if (git_repository_item_path(&src_odb, src, GIT_REPOSITORY_ITEM_OBJECTS) < 0 || git_repository_item_path(&dst_odb, repo, GIT_REPOSITORY_ITEM_OBJECTS) < 0) { error = -1; goto cleanup; } flags = 0; if (can_link(git_repository_path(src), git_repository_path(repo), link)) flags |= GIT_CPDIR_LINK_FILES; error = git_futils_cp_r(git_buf_cstr(&src_odb), git_buf_cstr(&dst_odb), flags, GIT_OBJECT_DIR_MODE); /* * can_link() doesn't catch all variations, so if we hit an * error and did want to link, let's try again without trying * to link. */ if (error < 0 && link) { flags &= ~GIT_CPDIR_LINK_FILES; error = git_futils_cp_r(git_buf_cstr(&src_odb), git_buf_cstr(&dst_odb), flags, GIT_OBJECT_DIR_MODE); } if (error < 0) goto cleanup; git_buf_printf(&reflog_message, "clone: from %s", git_remote_url(remote)); if ((error = git_remote_fetch(remote, NULL, fetch_opts, git_buf_cstr(&reflog_message))) != 0) goto cleanup; error = checkout_branch(repo, remote, co_opts, branch, git_buf_cstr(&reflog_message)); cleanup: git_buf_dispose(&reflog_message); git_buf_dispose(&src_path); git_buf_dispose(&src_odb); git_buf_dispose(&dst_odb); git_repository_free(src); return error; }
int CRepositoryBrowser::ReadTree(CShadowFilesTree * treeroot) { CStringA gitdir = CUnicodeUtils::GetMulti(g_Git.m_CurrentDir, CP_UTF8); git_repository *repository = NULL; git_commit *commit = NULL; git_tree * tree = NULL; int ret = 0; do { ret = git_repository_open(&repository, gitdir.GetBuffer()); if (ret) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not open repository.")), _T("TortoiseGit"), MB_ICONERROR); break; } if (m_sRevision == _T("HEAD")) { ret = git_repository_head_unborn(repository); if (ret == 1) // is orphan break; else if (ret != 0) { MessageBox(g_Git.GetLibGit2LastErr(_T("Could not check HEAD.")), _T("TortoiseGit"), MB_ICONERROR); break; } } CGitHash hash; if (g_Git.GetHash(hash, m_sRevision)) { MessageBox(g_Git.GetGitLastErr(_T("Could not get hash of ") + m_sRevision + _T(".")), _T("TortoiseGit"), MB_ICONERROR); break; } ret = git_commit_lookup(&commit, repository, (git_oid *) hash.m_hash); if (ret) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not lookup commit.")), _T("TortoiseGit"), MB_ICONERROR); break; } ret = git_commit_tree(&tree, commit); if (ret) { MessageBox(CGit::GetLibGit2LastErr(_T("Could not get tree of commit.")), _T("TortoiseGit"), MB_ICONERROR); break; } treeroot->m_hash = CGitHash((char *)git_tree_id(tree)->id); ReadTreeRecursive(*repository, tree, treeroot); // try to resolve hash to a branch name if (m_sRevision == hash.ToString()) { MAP_HASH_NAME map; if (g_Git.GetMapHashToFriendName(map)) MessageBox(g_Git.GetGitLastErr(_T("Could not get all refs.")), _T("TortoiseGit"), MB_ICONERROR); if (!map[hash].empty()) m_sRevision = map[hash].at(0); } this->GetDlgItem(IDC_BUTTON_REVISION)->SetWindowText(m_sRevision); } while(0); if (tree) git_tree_free(tree); if (commit) git_commit_free(commit); if (repository) git_repository_free(repository); return ret; }
/* * If it's not a git repo, return NULL. Be very conservative. */ struct git_repository *is_git_repository(const char *filename, const char **branchp, const char **remote, bool dry_run) { int flen, blen, ret; int offset = 1; struct stat st; git_repository *repo; char *loc, *branch; flen = strlen(filename); if (!flen || filename[--flen] != ']') return NULL; /* * Special-case "file://", and treat it as a local * repository since libgit2 is insanely slow for that. */ if (!strncmp(filename, "file://", 7)) { filename += 7; flen -= 7; } /* Find the matching '[' */ blen = 0; while (flen && filename[--flen] != '[') blen++; /* Ignore slashes at the end of the repo name */ while (flen && filename[flen-1] == '/') { flen--; offset++; } if (!flen) return NULL; /* * This is the "point of no return": the name matches * the git repository name rules, and we will no longer * return NULL. * * We will either return "dummy_git_repository" and the * branch pointer will have the _whole_ filename in it, * or we will return a real git repository with the * branch pointer being filled in with just the branch * name. * * The actual git reading/writing routines can use this * to generate proper error messages. */ *branchp = filename; loc = format_string("%.*s", flen, filename); if (!loc) return dummy_git_repository; branch = format_string("%.*s", blen, filename + flen + offset); if (!branch) { free(loc); return dummy_git_repository; } if (dry_run) { *branchp = branch; *remote = loc; return dummy_git_repository; } repo = is_remote_git_repository(loc, branch); if (repo) { if (remote) *remote = loc; else free(loc); *branchp = branch; return repo; } if (subsurface_stat(loc, &st) < 0 || !S_ISDIR(st.st_mode)) { if (verbose) fprintf(stderr, "loc %s wasn't found or is not a directory\n", loc); free(loc); free(branch); return dummy_git_repository; } ret = git_repository_open(&repo, loc); free(loc); if (ret < 0) { free(branch); return dummy_git_repository; } if (remote) *remote = NULL; *branchp = branch; return repo; }