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 85 alias BranchIterationDelegate = ContinueWalk delegate(GitBranch branch, GitBranchType type); 86 87 88 struct GitBranch { 89 protected this(GitReference ref_) 90 { 91 _ref = ref_; 92 } 93 94 @property inout(GitReference) reference() inout { return _ref; } 95 96 @property string name() 97 { 98 const(char)* ret; 99 require(git_branch_name(&ret, this.cHandle) == 0); 100 return ret.to!string(); 101 } 102 103 @property GitBranch upstream() 104 { 105 git_reference* ret; 106 require(git_branch_upstream(&ret, this.cHandle) == 0); 107 return GitBranch(GitReference(_ref.owner, ret)); 108 } 109 110 @property string upstreamName() 111 { 112 const(char)* branch_name; 113 require(git_branch_name(&branch_name, this.cHandle) == 0); 114 auto len = git_branch_upstream_name(null, 0, _ref.owner.cHandle, branch_name); 115 require(len > 0); 116 auto dst = new char[len]; 117 require(git_branch_upstream_name(dst.ptr, dst.length, _ref.owner.cHandle, branch_name) == len); 118 return cast(immutable)dst[0 .. $-1]; // skip trailing 0 119 } 120 121 @property void upstreamName(string name) 122 { 123 require(git_branch_set_upstream(_ref.cHandle, name.toStringz()) == 0); 124 } 125 126 @property bool isHead() { return requireBool(git_branch_is_head(_ref.cHandle)); } 127 128 @property string remoteName() 129 { 130 const(char)* branch_name; 131 require(git_branch_name(&branch_name, this.cHandle) == 0); 132 auto len = git_branch_remote_name(null, 0, _ref.owner.cHandle, branch_name); 133 require(len > 0); 134 auto dst = new char[len]; 135 require(git_branch_remote_name(dst.ptr, dst.length, _ref.owner.cHandle, branch_name) == len); 136 return cast(immutable)dst[0 .. $-1]; // skip trailing 0 137 } 138 139 GitBranch move(string new_name, bool force) 140 { 141 git_reference* dst; 142 require(git_branch_move(&dst, _ref.cHandle, new_name.toStringz(), force) == 0); 143 return GitBranch(GitReference(_ref.owner, dst)); 144 } 145 146 alias reference this; 147 148 private: 149 GitReference _ref; 150 }