summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeah (ctucx) <leah@ctu.cx>2021-03-23 20:13:56 +0100
committerLeah (ctucx) <leah@ctu.cx>2021-03-23 20:13:56 +0100
commitca7f01e88a829023e92d047d7a4537dea2c13a28 (patch)
tree127336ed1d88288d4224dfcc582376a2f74d5fbd
parent0c4ecd37247855fd7e3402cd17d3ec955970684f (diff)
downloadnimgit-ca7f01e88a829023e92d047d7a4537dea2c13a28.tar.gz
nimgit-ca7f01e88a829023e92d047d7a4537dea2c13a28.tar.bz2
nimgit-ca7f01e88a829023e92d047d7a4537dea2c13a28.zip
add diff-procs
-rw-r--r--nimgit.nim4
-rw-r--r--nimgit/diff.nim108
-rw-r--r--nimgit/free.nim4
-rw-r--r--nimgit/types.nim12
-rw-r--r--showLastCommit.nim44
5 files changed, 168 insertions, 4 deletions
diff --git a/nimgit.nim b/nimgit.nim
index 2237f23..c9fd4eb 100644
--- a/nimgit.nim
+++ b/nimgit.nim
@@ -1,5 +1,5 @@
import nimgit2
-import nimgit/[types, free, repository, config, objects, oid, tag, blob, tree, treeEntry, reference, revisionWalker, branch, commit]
+import nimgit/[types, free, repository, config, objects, oid, tag, blob, tree, treeEntry, reference, revisionWalker, branch, commit, diff]
export nimgit2
-export types, free, repository, config, objects, oid, tag, blob, tree, treeEntry, reference, revisionWalker, branch, commit
+export types, free, repository, config, objects, oid, tag, blob, tree, treeEntry, reference, revisionWalker, branch, commit, diff
diff --git a/nimgit/diff.nim b/nimgit/diff.nim
new file mode 100644
index 0000000..b8074b3
--- /dev/null
+++ b/nimgit/diff.nim
@@ -0,0 +1,108 @@
+import nimgit2
+import types, free
+
+proc initDiffOptions* (): GitDiffOptions =
+ result = cast[GitDiffOptions](sizeof(git_diff_options).alloc)
+ discard git_diff_init_options(result, GIT_DIFF_OPTIONS_VERSION)
+
+proc GitDiffFindOptions* (): GitDiffFindOptions =
+ result = cast[GitDiffFindOptions](sizeof(git_diff_find_options).alloc)
+ discard git_diff_find_init_options(result, GIT_DIFF_FIND_OPTIONS_VERSION)
+
+
+proc diffTrees* (repo: GitRepository, newTree: GitTree, oldTree: GitTree, options: GitDiffOptions): GitDiff =
+ let error = git_diff_tree_to_tree(addr result, repo, newTree, oldTree, options)
+
+ if error != 0:
+ free(result)
+ raise newException(CatchableError, "Cannot diff Trees: " & $error.getResultCode)
+
+proc findSimilar* (diff: GitDiff, options: GitDiffFindOptions) =
+ let error = git_diff_find_similar(diff, options)
+
+ if error != 0:
+ raise newException(CatchableError, "Cannot diff find: " & $error.getResultCode)
+
+proc stats* (diff: GitDiff): GitDiffStats =
+ var diffStats : ptr git_diff_stats
+ let error = git_diff_get_stats(addr diffStats, diff)
+
+ if error != 0:
+ raise newException(CatchableError, "Cannot get diff-stats: " & $error.getResultCode)
+
+ result.filesChanged = cast[int](git_diff_stats_files_changed(diffStats))
+ result.deletions = cast[int](git_diff_stats_deletions(diffStats))
+ result.insertions = cast[int](git_diff_stats_insertions(diffStats))
+
+ git_diff_stats_free(diffStats)
+
+proc len* (delta: GitDiff): int = cast[int](git_diff_num_deltas(delta))
+
+proc delta* (delta: GitDiff, id: int): GitDiffDelta = git_diff_get_delta(delta, uint(id))
+
+iterator deltas* (diff: GitDiff): (int, GitDiffDelta) =
+ var counter : int
+ let diffLen = diff.len
+
+ while counter < diffLen:
+ yield (counter, diff.delta(counter))
+ inc(counter)
+
+proc statusChar* (delta: GitDiffDelta): string =
+ case delta.status:
+ of GIT_DELTA_ADDED:
+ result = "A"
+ of GIT_DELTA_COPIED:
+ result = "C"
+ of GIT_DELTA_DELETED:
+ result = "D"
+ of GIT_DELTA_MODIFIED:
+ result = "M"
+ of GIT_DELTA_RENAMED:
+ result = "R"
+ of GIT_DELTA_TYPECHANGE:
+ result = "T"
+ else:
+ result = " "
+
+
+proc patch* (diff: GitDiff, id: int): GitPatch =
+ let error = git_patch_from_diff(addr result, diff, uint(id))
+
+ if error != 0:
+ raise newException(CatchableError, "Cannot get patch: " & $error.getResultCode)
+
+
+proc hunksLen* (patch: GitPatch): int = cast[int](git_patch_num_hunks(patch))
+
+proc hunk* (patch: GitPatch, id: int): GitDiffHunk =
+ var linesCount : uint
+ let error = git_patch_get_hunk(addr result, addr linesCount, patch, uint(id))
+
+ if error != 0:
+ raise newException(CatchableError, "Cannot get diff-hunk: " & $error.getResultCode)
+
+iterator hunks* (patch: GitPatch): (int, GitDiffHunk) =
+ var counter : int
+ let hunkLen = patch.hunksLen
+
+ while counter < hunkLen:
+ yield (counter, patch.hunk(counter))
+ inc(counter)
+
+
+proc linesLen* (patch: GitPatch, id: int): int = cast[int](git_patch_num_lines_in_hunk(patch, uint(id)))
+
+proc line* (patch: GitPatch, hunk: int, line: int): GitDiffLine =
+ let error = git_patch_get_line_in_hunk(addr result, patch, uint(hunk), uint(line))
+
+ if error != 0:
+ raise newException(CatchableError, "Cannot get diff-line: " & $error.getResultCode)
+
+iterator lines* (patch: GitPatch, hunkId: int): (int, GitDiffLine) =
+ var counter : int
+ let lineLen = patch.linesLen(hunkId)
+
+ while counter < lineLen:
+ yield (counter, patch.line(hunkId, counter))
+ inc(counter) \ No newline at end of file
diff --git a/nimgit/free.nim b/nimgit/free.nim
index c14fd72..bd84563 100644
--- a/nimgit/free.nim
+++ b/nimgit/free.nim
@@ -8,7 +8,7 @@ type
git_strarray | git_object | git_commit | git_status_list |
git_annotated_commit | git_tree_entry | git_revwalk | git_buf |
git_pathspec | git_tree | git_diff | git_pathspec_match_list |
- git_branch_iterator | git_signature | git_blob
+ git_branch_iterator | git_signature | git_blob | git_patch
proc free* [T: NimGitTypes] (point: ptr T) = dealloc(point)
@@ -55,3 +55,5 @@ proc free* [T: GitTypes] (point: ptr T) =
git_signature_free(point)
elif T is git_blob:
git_blob_free(point)
+ elif T is git_patch:
+ git_patch_free(point) \ No newline at end of file
diff --git a/nimgit/types.nim b/nimgit/types.nim
index 8b1c5b8..680fcaa 100644
--- a/nimgit/types.nim
+++ b/nimgit/types.nim
@@ -16,6 +16,18 @@ type
GitBuffer* = ptr git_buf
GitTag* = ptr git_tag
GitBlob* = ptr git_blob
+ GitDiff* = ptr git_diff
+ GitDiffOptions* = ptr git_diff_options
+ GitDiffFindOptions* = ptr git_diff_find_options
+ GitDiffDelta* = ptr git_diff_delta
+ GitPatch* = ptr git_patch
+ GitDiffHunk* = ptr git_diff_hunk
+ GitDiffLine* = ptr git_diff_line
+
+ GitDiffStats* = object
+ filesChanged* : int
+ insertions* : int
+ deletions* : int
GitObjectKind* = enum
# we have to add 2 here to satisfy nim; discriminants.low must be zero
diff --git a/showLastCommit.nim b/showLastCommit.nim
index 64804e2..564a1e2 100644
--- a/showLastCommit.nim
+++ b/showLastCommit.nim
@@ -1,4 +1,4 @@
-import os, times
+import os, times, bitops
import nimgit
if paramCount() == 0:
@@ -38,6 +38,48 @@ try:
echo ""
+ if commit.hasParents:
+ let parent = gitRepository.lookupCommit(commit.parentIds[0])
+ let parentTree = gitRepository.lookupTree(parent.treeId)
+
+ let diffopts = initDiffOptions()
+ diffopts.flags = cast[uint32](GIT_DIFF_DISABLE_PATHSPEC_MATCH) or cast[uint32](GIT_DIFF_IGNORE_SUBMODULES) or cast[uint32](GIT_DIFF_INCLUDE_TYPECHANGE)
+
+ let findopts = GitDiffFindOptions()
+ findopts.flags = cast[uint32](GIT_DIFF_FIND_RENAMES) or cast[uint32](GIT_DIFF_FIND_COPIES) or cast[uint32](GIT_DIFF_FIND_EXACT_MATCH_ONLY)
+
+ let diff = gitRepository.diffTrees(tree, parentTree, diffopts)
+ diff.findSimilar(findopts)
+
+ free(parentTree)
+ free(parent)
+
+ echo diff.len
+ echo diff.stats
+
+ for deltaIndex, delta in diff.deltas:
+ echo delta.statusChar & " " & $delta.old_file.path & " " & $delta.new_file.path
+
+ let patch = diff.patch(deltaIndex)
+
+ for hunkIndex, hunk in patch.hunks():
+
+ echo $hunk.header
+
+ for lineIndex, line in patch.lines(hunkIndex):
+ var status: string
+
+ if line.old_lineno == -1:
+ status = "+"
+ elif line.new_lineno == -1:
+ status = "-"
+ else:
+ status = " "
+
+ echo status & $line.content
+
+ free(patch)
+
free(tree)
free(commit)
free(config)