1 /* 2 * Copyright Sönke Ludwig 2014. 3 * Distributed under the Boost Software License, Version 1.0. 4 * (See accompanying file LICENSE_1_0.txt or copy at 5 * http://www.boost.org/LICENSE_1_0.txt) 6 */ 7 module git.branch; 8 9 import git.commit; 10 import git.oid; 11 import git.reference; 12 import git.repository; 13 import git.types; 14 import git.util; 15 import git.version_; 16 17 import deimos.git2.branch; 18 import deimos.git2.errors; 19 import deimos.git2.types; 20 21 import std.conv : to; 22 import std.string : toStringz; 23 24 25 GitBranch createBranch(GitRepo repo, string name, GitCommit target, bool force) 26 { 27 git_reference* ret; 28 require(git_branch_create(&ret, repo.cHandle, name.toStringz, target.cHandle, force) == 0); 29 return GitBranch(GitReference(repo, ret)); 30 } 31 32 GitBranch lookupBranch(GitRepo repo, string name, GitBranchType type) 33 { 34 git_reference* ret; 35 require(git_branch_lookup(&ret, repo.cHandle, name.toStringz(), cast(git_branch_t)type) == 0); 36 return GitBranch(GitReference(repo, ret)); 37 } 38 39 void deleteBranch(GitBranch branch) 40 { 41 require(git_branch_delete(branch.cHandle) == 0); 42 } 43 44 void iterateBranches(GitRepo repo, GitBranchType types, scope BranchIterationDelegate del) 45 { 46 static if (targetLibGitVersion == VersionInfo(0, 19, 0)) { 47 static struct CTX { BranchIterationDelegate del; GitRepo repo; Exception e; } 48 static extern(C) nothrow int callback(const(char)* name, git_branch_t type, void* payload) { 49 auto ctx = cast(CTX*)payload; 50 try { 51 auto gtp = cast(GitBranchType)type; 52 if (ctx.del(lookupBranch(ctx.repo, name.to!string, gtp), gtp) == ContinueWalk.no) 53 return 1; 54 } catch (Exception e) { 55 ctx.e = e; 56 return -1; 57 } 58 return 0; 59 } 60 61 auto ctx = CTX(del, repo); 62 auto ret = git_branch_foreach(repo.cHandle, cast(git_branch_t)types, &callback, &ctx); 63 if (ret == GIT_EUSER) { 64 if (ctx.e) throw ctx.e; 65 else return; 66 } 67 require(ret == 0); 68 } else { 69 git_branch_iterator* it; 70 require(git_branch_iterator_new(&it, repo.cHandle, cast(git_branch_t)types) == 0); 71 scope (exit) git_branch_iterator_free(it); 72 while (true) { 73 git_reference* br; 74 git_branch_t brtp; 75 auto ret = git_branch_next(&br, &brtp, it); 76 if (ret == GIT_ITEROVER) break; 77 require(ret == 0); 78 if (del(GitBranch(GitReference(repo, br)), cast(GitBranchType)brtp) == ContinueWalk.no) 79 break; 80 } 81 } 82 } 83 84 enum GitBranchType { 85 local = GIT_BRANCH_LOCAL, 86 remote = GIT_BRANCH_REMOTE 87 } 88 89 alias BranchIterationDelegate = ContinueWalk delegate(GitBranch branch, GitBranchType type); 90 91 struct GitBranch { 92 protected this(GitReference ref_) 93 { 94 _ref = ref_; 95 } 96 97 @property inout(GitReference) reference() inout { return _ref; } 98 99 @property string name() 100 { 101 const(char)* ret; 102 require(git_branch_name(&ret, this.cHandle) == 0); 103 return ret.to!string(); 104 } 105 106 @property GitBranch upstream() 107 { 108 git_reference* ret; 109 require(git_branch_upstream(&ret, this.cHandle) == 0); 110 return GitBranch(GitReference(_ref.owner, ret)); 111 } 112 113 @property string upstreamName() 114 { 115 const(char)* branch_name; 116 require(git_branch_name(&branch_name, this.cHandle) == 0); 117 auto len = git_branch_upstream_name(null, 0, _ref.owner.cHandle, branch_name); 118 require(len > 0); 119 auto dst = new char[len]; 120 require(git_branch_upstream_name(dst.ptr, dst.length, _ref.owner.cHandle, branch_name) == len); 121 return cast(immutable)dst[0 .. $-1]; // skip trailing 0 122 } 123 124 @property void upstreamName(string name) 125 { 126 require(git_branch_set_upstream(_ref.cHandle, name.toStringz()) == 0); 127 } 128 129 @property bool isHead() { return requireBool(git_branch_is_head(_ref.cHandle)); } 130 131 @property string remoteName() 132 { 133 const(char)* branch_name; 134 require(git_branch_name(&branch_name, this.cHandle) == 0); 135 auto len = git_branch_remote_name(null, 0, _ref.owner.cHandle, branch_name); 136 require(len > 0); 137 auto dst = new char[len]; 138 require(git_branch_remote_name(dst.ptr, dst.length, _ref.owner.cHandle, branch_name) == len); 139 return cast(immutable)dst[0 .. $-1]; // skip trailing 0 140 } 141 142 GitBranch move(string new_name, bool force) 143 { 144 git_reference* dst; 145 require(git_branch_move(&dst, _ref.cHandle, new_name.toStringz(), force) == 0); 146 return GitBranch(GitReference(_ref.owner, dst)); 147 } 148 149 alias reference this; 150 151 private: 152 GitReference _ref; 153 }