mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
Add method to get ahead/behind commit counts
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#import "git.h"
|
||||
#import "include/git2.h"
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import <stdlib.h>
|
||||
|
||||
namespace v8_extensions {
|
||||
|
||||
@@ -74,6 +75,106 @@ namespace v8_extensions {
|
||||
return v8Statuses;
|
||||
}
|
||||
|
||||
int getCommitCount(const git_oid* fromCommit, const git_oid* toCommit) {
|
||||
int count = 0;
|
||||
git_revwalk *revWalk;
|
||||
if (git_revwalk_new(&revWalk, repo) == GIT_OK) {
|
||||
git_revwalk_push(revWalk, fromCommit);
|
||||
git_revwalk_hide(revWalk, toCommit);
|
||||
git_oid currentCommit;
|
||||
while (git_revwalk_next(¤tCommit, revWalk) == GIT_OK)
|
||||
count++;
|
||||
git_revwalk_free(revWalk);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void getShortBranchName(const char** out, const char* branchName) {
|
||||
*out = NULL;
|
||||
if (branchName == NULL)
|
||||
return;
|
||||
int branchNameLength = strlen(branchName);
|
||||
if (branchNameLength < 12)
|
||||
return;
|
||||
if (strncmp("refs/heads/", branchName, 11) != 0)
|
||||
return;
|
||||
|
||||
int shortNameLength = branchNameLength - 11;
|
||||
char* shortName = (char*) malloc(sizeof(char) * shortNameLength + 1);
|
||||
shortName[shortNameLength] = '\0';
|
||||
strncpy(shortName, &branchName[11], shortNameLength);
|
||||
*out = shortName;
|
||||
}
|
||||
|
||||
void getUpstreamBranch(const char** out, git_reference *branch) {
|
||||
*out = NULL;
|
||||
git_config *config;
|
||||
if (git_repository_config(&config, repo) != GIT_OK)
|
||||
return;
|
||||
|
||||
const char* branchName = git_reference_name(branch);
|
||||
const char* shortBranchName;
|
||||
getShortBranchName(&shortBranchName, branchName);
|
||||
if (shortBranchName == NULL)
|
||||
return;
|
||||
|
||||
int shortBranchNameLength = strlen(shortBranchName);
|
||||
char* remoteKey = (char*) malloc(sizeof(char) * shortBranchNameLength + 15);
|
||||
remoteKey[shortBranchNameLength + 14] = '\0';
|
||||
sprintf(remoteKey, "branch.%s.remote", shortBranchName);
|
||||
char* mergeKey = (char*) malloc(sizeof(char) * shortBranchNameLength + 14);
|
||||
mergeKey[shortBranchNameLength + 13] = '\0';
|
||||
sprintf(mergeKey, "branch.%s.merge", shortBranchName);
|
||||
free((char*)shortBranchName);
|
||||
|
||||
const char *remote;
|
||||
const char *merge;
|
||||
if (git_config_get_string(&remote, config, remoteKey) == GIT_OK
|
||||
&& git_config_get_string(&merge, config, mergeKey) == GIT_OK) {
|
||||
const char* shortMergeBranchName;
|
||||
getShortBranchName(&shortMergeBranchName, merge);
|
||||
if (shortMergeBranchName != NULL) {
|
||||
int shortMergeBranchNameLength = strlen(shortMergeBranchName);
|
||||
int updateRefLength = strlen(remote) + shortMergeBranchNameLength + 15;
|
||||
char* upstreamBranch = (char*) malloc(sizeof(char) * updateRefLength);
|
||||
sprintf(upstreamBranch, "refs/remotes/%s/%s", remote, shortMergeBranchName);
|
||||
free((char*)shortMergeBranchName);
|
||||
*out = upstreamBranch;
|
||||
}
|
||||
}
|
||||
|
||||
free(remoteKey);
|
||||
free(mergeKey);
|
||||
git_config_free(config);
|
||||
}
|
||||
|
||||
CefRefPtr<CefV8Value> GetAheadBehindCounts() {
|
||||
CefRefPtr<CefV8Value> result = CefV8Value::CreateObject(NULL);
|
||||
git_reference *head;
|
||||
if (git_repository_head(&head, repo) == GIT_OK) {
|
||||
const char* upstreamBranchName;
|
||||
getUpstreamBranch(&upstreamBranchName, head);
|
||||
if (upstreamBranchName != NULL) {
|
||||
git_reference *upstream;
|
||||
if (git_reference_lookup(&upstream, repo, upstreamBranchName) == GIT_OK) {
|
||||
const git_oid* headSha = git_reference_target(head);
|
||||
const git_oid* upstreamSha = git_reference_target(upstream);
|
||||
git_oid mergeBase;
|
||||
if (git_merge_base(&mergeBase, repo, headSha, upstreamSha) == GIT_OK) {
|
||||
int ahead = getCommitCount(headSha, &mergeBase);
|
||||
result->SetValue("ahead", CefV8Value::CreateInt(ahead), V8_PROPERTY_ATTRIBUTE_NONE);
|
||||
int behind = getCommitCount(upstreamSha, &mergeBase);
|
||||
result->SetValue("behind", CefV8Value::CreateInt(behind), V8_PROPERTY_ATTRIBUTE_NONE);
|
||||
}
|
||||
git_reference_free(upstream);
|
||||
}
|
||||
free((char*)upstreamBranchName);
|
||||
}
|
||||
git_reference_free(head);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
CefRefPtr<CefV8Value> IsIgnored(const char *path) {
|
||||
int ignored;
|
||||
if (git_ignore_path_is_ignored(&ignored, repo, path) == GIT_OK) {
|
||||
@@ -209,7 +310,8 @@ namespace v8_extensions {
|
||||
void Git::CreateContextBinding(CefRefPtr<CefV8Context> context) {
|
||||
const char* methodNames[] = {
|
||||
"getRepository", "getHead", "getPath", "isIgnored", "getStatus", "checkoutHead",
|
||||
"getDiffStats", "isSubmodule", "refreshIndex", "destroy", "getStatuses"
|
||||
"getDiffStats", "isSubmodule", "refreshIndex", "destroy", "getStatuses",
|
||||
"getAheadBehindCounts"
|
||||
};
|
||||
|
||||
CefRefPtr<CefV8Value> nativeObject = CefV8Value::CreateObject(NULL);
|
||||
@@ -302,6 +404,12 @@ namespace v8_extensions {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name == "getAheadBehindCounts") {
|
||||
GitRepository *userData = (GitRepository *)object->GetUserData().get();
|
||||
retval = userData->GetAheadBehindCounts();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,5 +138,8 @@ class Git
|
||||
directoryStatus |= status if path.indexOf(directoryPath) is 0
|
||||
directoryStatus
|
||||
|
||||
getAheadBehindCounts: ->
|
||||
@getRepo().getAheadBehindCounts()
|
||||
|
||||
_.extend Git.prototype, Subscriber
|
||||
_.extend Git.prototype, EventEmitter
|
||||
|
||||
@@ -17,3 +17,4 @@ class GitRepository
|
||||
isSubmodule: $git.isSubmodule
|
||||
refreshIndex: $git.refreshIndex
|
||||
destroy: $git.destroy
|
||||
getAheadBehindCounts: $git.getAheadBehindCounts
|
||||
|
||||
Reference in New Issue
Block a user