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.index;
8 
9 import git.commit;
10 import git.oid;
11 import git.tree;
12 import git.repository;
13 import git.types;
14 import git.util;
15 import git.version_;
16 
17 import deimos.git2.index;
18 import deimos.git2.errors;
19 import deimos.git2.types;
20 
21 import std.conv : to;
22 import std..string : toStringz;
23 
24 
25 GitIndex openIndex(string index_path)
26 {
27 	git_index* dst;
28 	require(git_index_open(&dst, index_path.toStringz) == 0);
29 	return GitIndex(dst);
30 }
31 
32 GitIndex createIndex()
33 {
34 	git_index* dst;
35 	require(git_index_new(&dst) == 0);
36 	return GitIndex(dst);
37 }
38 
39 struct GitIndex {
40 	this(git_index* index)
41 	{
42 		_repo = GitRepo.init;
43 		_data = Data(index);
44 	}
45 
46 	this(GitRepo repo, git_index* index)
47 	{
48 		_repo = repo;
49 		_data = Data(index);
50 	}
51 
52 	@property inout(GitRepo) owner() inout { return _repo; }
53 
54 	@property GitIndexCaps caps() { return cast(GitIndexCaps)git_index_caps(this.cHandle); }
55 	@property void caps(GitIndexCaps caps) { require(git_index_set_caps(this.cHandle, caps) == 0); }
56 
57 	static if (targetLibGitVersion >= VersionInfo(0, 20, 0))
58 		@property string path() { return git_index_path(this.cHandle).to!string; }
59 
60 	@property size_t entryCount() { return git_index_entrycount(this.cHandle); }
61 
62 	static if (targetLibGitVersion >= VersionInfo(0, 20, 0))
63 		void read(bool force) { require(git_index_read(this.cHandle, force) == 0); }
64 	else void read() { require(git_index_read(this.cHandle) == 0); }
65 	void write() { require(git_index_write(this.cHandle) == 0); }
66 
67 	void readTree(in GitTree tree) { require(git_index_read_tree(this.cHandle, tree.cHandle) == 0); }
68 	GitOid writeTree()
69 	{
70 		GitOid ret;
71 		require(git_index_write_tree(&ret._get_oid(), this.cHandle) == 0);
72 		return ret;
73 	}
74 	GitOid writeTree(GitRepo repo)
75 	{
76 		GitOid ret;
77 		require(git_index_write_tree_to(&ret._get_oid(), this.cHandle, repo.cHandle) == 0);
78 		return ret;
79 	}
80 
81 	void clear() { git_index_clear(this.cHandle); }
82 
83 	GitIndexEntry get(size_t n) { return GitIndexEntry(this, git_index_get_byindex(this.cHandle, n)); }
84 	GitIndexEntry get(string path, int stage) { return GitIndexEntry(this, git_index_get_bypath(this.cHandle, path.toStringz, stage)); }
85 
86 	void remove(string path, int stage) { require(git_index_remove(this.cHandle, path.toStringz, stage) == 0); }
87 	void removeDirectory(string dir, int stage) { require(git_index_remove_directory(this.cHandle, dir.toStringz, stage) == 0); }
88 	void add(GitIndexEntry source_entry) { require(git_index_add(this.cHandle, source_entry.cHandle) == 0); }
89 	void addByPath(string path) { require(git_index_add_bypath(this.cHandle, path.toStringz) == 0); }
90 	void removeByPath(string path) { require(git_index_remove_bypath(this.cHandle, path.toStringz) == 0); }
91 
92 /*
93 int git_index_add_all(
94 	git_index *index,
95 	const(git_strarray)* pathspec,
96 	uint flags,
97 	git_index_matched_path_cb callback,
98 	void *payload);
99 int git_index_remove_all(
100 	git_index *index,
101 	const(git_strarray)* pathspec,
102 	git_index_matched_path_cb callback,
103 	void *payload);
104 int git_index_update_all(
105 	git_index *index,
106 	const(git_strarray)* pathspec,
107 	git_index_matched_path_cb callback,
108 	void *payload);
109 int git_index_find(size_t *at_pos, git_index *index, const(char)* path);
110 int git_index_conflict_add(
111 	git_index *index,
112 	const(git_index_entry)* ancestor_entry,
113 	const(git_index_entry)* our_entry,
114 	const(git_index_entry)* their_entry);
115 int git_index_conflict_get(
116 	const(git_index_entry)** ancestor_out,
117 	const(git_index_entry)** our_out,
118 	const(git_index_entry)** their_out,
119 	git_index *index,
120 	const(char)* path);
121 int git_index_conflict_remove(git_index *index, const(char)* path);
122 void git_index_conflict_cleanup(git_index *index);
123 */
124 
125 	bool hasConflicts()
126 	{
127 		return git_index_has_conflicts(this.cHandle) != 0;
128 	}
129 
130 	int conflictIterator(int delegate(GitIndexEntry ancestor, GitIndexEntry our, GitIndexEntry their) dg)
131 	{
132 		git_index_conflict_iterator* it;
133 		require(git_index_conflict_iterator_new(&it, this.cHandle) == 0);
134 		scope (exit) git_index_conflict_iterator_free(it);
135 		while (true) {
136 			const(git_index_entry)* ancestor, our, their;
137 			auto ret = git_index_conflict_next(&ancestor, &our, &their, it);
138 			if (ret == GIT_ITEROVER) break;
139 			require(ret == 0);
140 			ret = dg(GitIndexEntry(this, ancestor), GitIndexEntry(this, our), GitIndexEntry(this, their));
141 			if (ret)
142 				return ret;
143 		}
144 		return 0;
145 	}
146 
147 /*
148 int git_index_conflict_iterator_new(
149 	git_index_conflict_iterator **iterator_out,
150 	git_index *index);
151 int git_index_conflict_next(
152 	const(git_index_entry)** ancestor_out,
153 	const(git_index_entry)** our_out,
154 	const(git_index_entry)** their_out,
155 	git_index_conflict_iterator *iterator);
156 void git_index_conflict_iterator_free(
157 	git_index_conflict_iterator *iterator);
158 int git_index_entry_stage(const(git_index_entry)* entry);*/
159 
160 	mixin RefCountedGitObject!(git_index, git_index_free);
161 	private GitRepo _repo;
162 }
163 
164 
165 struct GitIndexEntry {
166 	package this(GitIndex index, const(git_index_entry)* entry)
167 	{
168 		_index = index;
169 		_entry = entry;
170 	}
171 
172 	//@property SysTime ctime() const { return gitIndexTimeToSysTime(_entry.ctime); }
173 	//@property SysTime mtime() const { return gitIndexTimeToSysTime(_entry.mtime); }
174 	@property uint dev() const { return _entry.dev; }
175 	@property uint ino() const { return _entry.ino; }
176 	@property uint mode() const { return _entry.mode; }
177 	@property uint uid() const { return _entry.uid; }
178 	@property uint gid() const { return _entry.gid; }
179 	@property ulong fileSize() const { return _entry.file_size; }
180 	@property GitOid oid() const { return GitOid(_entry.oid); }
181 	@property string path() const { return _entry.path.to!string; }
182 	@property int stage() { return git_index_entry_stage(_entry); }
183 
184 	//ushort flags;
185 	//ushort flags_extended;
186 
187 	package @property const(git_index_entry)* cHandle() const { return _entry; }
188 
189 	private const(git_index_entry)* _entry;
190 	private GitIndex _index;
191 }
192 
193 enum GitIndexCaps {
194 	none = 0,
195 	ignoreCase = GIT_INDEXCAP_IGNORE_CASE,
196 	noFilemode = GIT_INDEXCAP_NO_FILEMODE,
197 	noSymlinks = GIT_INDEXCAP_NO_SYMLINKS,
198 	fromOwner = GIT_INDEXCAP_FROM_OWNER
199 }
200 
201 /*struct git_index_time {
202 	git_time_t seconds;
203 	uint nanoseconds;
204 }
205 
206 enum GIT_IDXENTRY_NAMEMASK   = (0x0fff);
207 enum GIT_IDXENTRY_STAGEMASK  = (0x3000);
208 enum GIT_IDXENTRY_EXTENDED   = (0x4000);
209 enum GIT_IDXENTRY_VALID      = (0x8000);
210 enum GIT_IDXENTRY_STAGESHIFT = 12;
211 
212 auto GIT_IDXENTRY_STAGE(T)(T E) { return (((E).flags & GIT_IDXENTRY_STAGEMASK) >> GIT_IDXENTRY_STAGESHIFT); }
213 
214 enum GIT_IDXENTRY_INTENT_TO_ADD     = (1 << 13);
215 enum GIT_IDXENTRY_SKIP_WORKTREE     = (1 << 14);
216 enum GIT_IDXENTRY_EXTENDED2         = (1 << 15);
217 enum GIT_IDXENTRY_EXTENDED_FLAGS = (GIT_IDXENTRY_INTENT_TO_ADD | GIT_IDXENTRY_SKIP_WORKTREE);
218 
219 enum GIT_IDXENTRY_UPDATE            = (1 << 0);
220 enum GIT_IDXENTRY_REMOVE            = (1 << 1);
221 enum GIT_IDXENTRY_UPTODATE          = (1 << 2);
222 enum GIT_IDXENTRY_ADDED             = (1 << 3);
223 
224 enum GIT_IDXENTRY_HASHED            = (1 << 4);
225 enum GIT_IDXENTRY_UNHASHED          = (1 << 5);
226 enum GIT_IDXENTRY_WT_REMOVE         = (1 << 6);
227 enum GIT_IDXENTRY_CONFLICTED        = (1 << 7);
228 
229 enum GIT_IDXENTRY_UNPACKED          = (1 << 8);
230 enum GIT_IDXENTRY_NEW_SKIP_WORKTREE = (1 << 9);
231 
232 
233 alias git_index_matched_path_cb = int function(
234 	const(char)* path, const(char)* matched_pathspec, void *payload);
235 
236 enum git_index_add_option_t {
237 	GIT_INDEX_ADD_DEFAULT = 0,
238 	GIT_INDEX_ADD_FORCE = (1u << 0),
239 	GIT_INDEX_ADD_DISABLE_PATHSPEC_MATCH = (1u << 1),
240 	GIT_INDEX_ADD_CHECK_PATHSPEC = (1u << 2),
241 }
242 
243 enum GIT_INDEX_STAGE_ANY = -1;
244 */