Improve samples (#396)

This commit is contained in:
Nikolay Igotti
2017-03-27 18:16:06 +03:00
committed by GitHub
parent c4abb8f706
commit a6656a0cba
15 changed files with 336 additions and 9 deletions
@@ -95,7 +95,7 @@ private fun ProcessBuilder.runExpectingSuccess() {
}
private fun Properties.getSpaceSeparated(name: String): List<String> {
return this.getProperty(name)?.split(' ') ?: emptyList()
return this.getProperty(name)?.split(' ')?.filter { it.isNotEmpty() } ?: emptyList()
}
private fun Properties.getOsSpecific(name: String,
+3 -4
View File
@@ -1,6 +1,6 @@
# CVS parser
# CSV parser
This example shows how one could implement simple CSV reader and parser in Kotlin.
This example shows how one could implement simple comma separated values reader and parser in Kotlin.
A sample data [European Mammals Red List for 2009] (https://data.europa.eu/euodp/en/data/dataset?res_format=CSV)
from EU is being used.
@@ -10,5 +10,4 @@ To run use
./CsvParser.kexe ./European_Mammals_Red_List_Nov_2009.csv 4 100
Which will print fifth column (Family, zero-based index) in first 100 rows of the
CSV file.
It will print fifth column (Family, zero-based index) in first 100 rows of the CSV file.
+11
View File
@@ -0,0 +1,11 @@
# GIT frequency analyzer
This example shows how one could perform statistics on Git repository.
To build use `./build.sh` script without arguments (or specify `TARGET` variable if cross-compiling).
To run use
./GitChurn.kexe <path-to-some-git-repo>
It will print most frequently modified (by number of commits) files in repository.
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
PATH=../../dist/bin:../../bin:$PATH
DIR=.
CFLAGS_macbook=-I/opt/local/include
CFLAGS_linux=-I/usr/include
LINKER_ARGS_macbook="-L/opt/local/lib -lgit2"
LINKER_ARGS_linux="-L/usr/lib/x86_64-linux-gnu -lgit2"
if [ x$TARGET == x ]; then
case "$OSTYPE" in
darwin*) TARGET=macbook ;;
linux*) TARGET=linux ;;
*) echo "unknown: $OSTYPE" && exit 1;;
esac
fi
var=CFLAGS_${TARGET}
CFLAGS=${!var}
var=LINKER_ARGS_${TARGET}
LINKER_ARGS=${!var}
var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build.
interop -copt:$CFLAGS -def:$DIR/libgit2.def -target:$TARGET || exit 1
konanc -target $TARGET src libgit2 -nativelibrary libgit2stubs.bc -linkerArgs "$LINKER_ARGS" -o GitChurn.kexe || exit 1
+3
View File
@@ -0,0 +1,3 @@
headers = git2.h
linkerOpts = -lgit2
excludedFunctions =
+3
View File
@@ -0,0 +1,3 @@
fun main(args: Array<String>) {
org.konan.libgit.main(args)
}
@@ -0,0 +1,69 @@
package org.konan.libgit
import kotlinx.cinterop.*
import libgit2.*
fun main(args: Array<String>) {
if (args.size == 0)
return help()
val workDir = args[0]
val limit = if (args.size > 1) {
args[1].toInt()
} else
null
println("Opening…")
val repository = git.repository(workDir)
val map = mutableMapOf<String, Int>()
var count = 0
val commits = repository.commits()
val limited = limit?.let { commits.take(it) } ?: commits
println("Calculating…")
limited.forEach { commit ->
if (count % 100 == 0)
println("Commit #$count [${commit.time.format()}]: ${commit.summary}")
commit.parents.forEach { parent ->
val diff = commit.tree.diff(parent.tree)
diff.deltas().forEach { delta ->
val path = delta.newPath
val n = map[path] ?: 0
map.put(path, n + 1)
}
diff.close()
parent.close()
}
commit.close()
count++
}
println("Report:")
map.toList().sortedByDescending { it.second }.take(10).forEach {
println("File: ${it.first}")
println(" ${it.second}")
println()
}
repository.close()
git.close()
}
fun git_time_t.format() = memScoped {
val commitTime = alloc<time_tVar>()
commitTime.value = this@format
ctime(commitTime.ptr)!!.toKString().trim()
}
private fun printTree(commit: GitCommit) {
commit.tree.entries().forEach { entry ->
when (entry) {
is GitTreeEntry.File -> println(" ${entry.name}")
is GitTreeEntry.Folder -> println(" /${entry.name} (${entry.subtree.entries().size})")
}
}
}
fun help() {
println("Working directory should be provided")
}
@@ -0,0 +1,28 @@
package org.konan.libgit
import kotlinx.cinterop.*
import libgit2.*
class GitCommit(val repository: GitRepository, val commit: CPointer<git_commit>) {
fun close() = git_commit_free(commit)
val summary: String get() = git_commit_summary(commit)!!.toKString()
val time: git_time_t get() = git_commit_time(commit)
val tree: GitTree get() = memScoped {
val treePtr = allocPointerTo<git_tree>()
git_commit_tree(treePtr.ptr, commit).errorCheck()
GitTree(repository, treePtr.value!!)
}
val parents: List<GitCommit> get() = memScoped {
val count = git_commit_parentcount(commit)
val result = ArrayList<GitCommit>(count)
for (index in 0..count - 1) {
val commitPtr = allocPointerTo<git_commit>()
git_commit_parent(commitPtr.ptr, commit, index).errorCheck()
result.add(GitCommit(repository, commitPtr.value!!))
}
result
}
}
@@ -0,0 +1,40 @@
package org.konan.libgit
import kotlinx.cinterop.*
import libgit2.*
class GitDiff(val repository: GitRepository, val handle: CPointer<git_diff>) {
fun deltas(): List<GifDiffDelta> {
val size = git_diff_num_deltas(handle)
val results = ArrayList<GifDiffDelta>(size.toInt())
for (index in 0..size - 1) {
val delta = git_diff_get_delta(handle, index)
results.add(GifDiffDelta(this, delta!!))
}
return results
}
fun close() {
git_diff_free(handle)
}
}
class GifDiffDelta(val diff: GitDiff, val handle: CPointer<git_diff_delta>) {
val status get() = handle.pointed.status.value
val newPath get() = handle.pointed.new_file.path.value!!.toKString()
val oldPath get() = handle.pointed.old_file.path.value!!.toKString()
fun status(): String {
return when (status) {
GIT_DELTA_ADDED -> "A"
GIT_DELTA_DELETED -> "D"
GIT_DELTA_MODIFIED -> "M"
GIT_DELTA_RENAMED -> "R"
GIT_DELTA_COPIED -> "C"
else -> throw Exception("Unsupported delta status $status")
}
}
}
@@ -0,0 +1,11 @@
package org.konan.libgit
import kotlinx.cinterop.*
import libgit2.*
class GitRemote(val repository: GitRepository, val handle: CPointer<git_remote>) {
fun close() = git_remote_free(handle)
val url: String get() = git_remote_url(handle)!!.toKString()
val name: String = git_remote_name(handle)!!.toKString()
}
@@ -0,0 +1,58 @@
package org.konan.libgit
import kotlinx.cinterop.*
import libgit2.*
class GitRepository(val location: String) {
val arena = Arena()
val handle: CPointer<git_repository> = memScoped {
val loc = allocPointerTo<git_repository>()
git_repository_open(loc.ptr, location).errorCheck()
loc.value!!
}
fun close() {
git_repository_free(handle)
arena.clear()
}
fun remotes(): List<GitRemote> = memScoped {
val remoteList = alloc<git_strarray>()
git_remote_list(remoteList.ptr, handle).errorCheck()
val size = remoteList.count.value.toInt()
val list = ArrayList<GitRemote>(size)
for (index in 0..size - 1) {
val array = remoteList.strings.value!!.reinterpret<CArray<CPointerVar<CInt8Var>>>().pointed
val name = array[index].value!!.toKString()
val remotePtr = allocPointerTo<git_remote>()
git_remote_lookup(remotePtr.ptr, handle, name).errorCheck()
list.add(GitRemote(this@GitRepository, remotePtr.value!!))
}
list
}
fun commits(): Sequence<GitCommit> = memScoped {
val walkPtr = allocPointerTo<git_revwalk>()
git_revwalk_new(walkPtr.ptr, handle).errorCheck()
val walk = walkPtr.value
git_revwalk_sorting(walk, GIT_SORT_TOPOLOGICAL or GIT_SORT_TIME)
git_revwalk_push_head(walk).errorCheck()
generateSequence<GitCommit> {
memScoped {
val oid = alloc<git_oid>()
val result = git_revwalk_next(oid.ptr, walk)
when (result) {
0 -> {
val commitPtr = allocPointerTo<git_commit>()
git_commit_lookup(commitPtr.ptr, handle, oid.ptr).errorCheck()
val commit = commitPtr.value!!
GitCommit(this@GitRepository, commit)
}
GIT_ITEROVER -> null
else -> throw Exception("Unexpected result code $result")
}
}
}
}
}
@@ -0,0 +1,45 @@
package org.konan.libgit
import kotlinx.cinterop.*
import libgit2.*
class GitTree(val repository: GitRepository, val handle: CPointer<git_tree>) {
fun close() = git_tree_free(handle)
fun entries(): List<GitTreeEntry> = memScoped {
val size = git_tree_entrycount(handle)
val entries = ArrayList<GitTreeEntry>(size.toInt())
for (index in 0..size - 1) {
val treeEntry = git_tree_entry_byindex(handle, index)!!
val entryType = git_tree_entry_type(treeEntry)
val entry = when (entryType) {
GIT_OBJ_TREE -> memScoped {
val id = git_tree_entry_id(treeEntry)
val treePtr = allocPointerTo<git_tree>()
git_tree_lookup(treePtr.ptr, repository.handle, id)
GitTreeEntry.Folder(this@GitTree, treeEntry, treePtr.value!!)
}
GIT_OBJ_BLOB -> GitTreeEntry.File(this@GitTree, treeEntry)
else -> throw Exception("Unsupported entry type $entryType")
}
entries.add(entry)
}
entries
}
fun diff(other: GitTree): GitDiff = memScoped {
val diffPtr = allocPointerTo<git_diff>()
git_diff_tree_to_tree(diffPtr.ptr, repository.handle, handle, other.handle, null).errorCheck()
GitDiff(repository, diffPtr.value!!)
}
}
sealed class GitTreeEntry(val tree: GitTree, val handle: CPointer<git_tree_entry>) {
val name: String get() = git_tree_entry_name(handle)!!.toKString()
class Folder(tree: GitTree, handle: CPointer<git_tree_entry>, val subtreeHandle: CPointer<git_tree>) : GitTreeEntry(tree, handle) {
val subtree = GitTree(tree.repository, subtreeHandle)
}
class File(tree: GitTree, handle: CPointer<git_tree_entry>) : GitTreeEntry(tree, handle)
}
@@ -0,0 +1,28 @@
package org.konan.libgit
import kotlinx.cinterop.*
import libgit2.*
object git {
init {
git_libgit2_init()
}
fun close() {
git_libgit2_shutdown()
}
fun repository(location: String): GitRepository {
return GitRepository(location)
}
}
fun Int.errorCheck() {
if (this == 0) return
throw GitException()
}
class GitException : Exception(run {
val err = giterr_last()
err!!.pointed.message.value!!.toKString()
})
+3 -2
View File
@@ -4,7 +4,7 @@ PATH=../../dist/bin:../../bin:$PATH
DIR=.
LINKER_ARGS_macbook="-framework OpenGL -framework GLUT"
LINKER_ARGS_linux="-L/usr/lib/x86_64-linux-gnu -lSDL2"
LINKER_ARGS_linux="-L/usr/lib/x86_64-linux-gnu -lglut -lGL -lGLU"
if [ x$TARGET == x ]; then
case "$OSTYPE" in
@@ -22,4 +22,5 @@ var=COMPILER_ARGS_${TARGET}
COMPILER_ARGS=${!var} # add -opt for an optimized build.
interop -def:$DIR/opengl.def -target:$TARGET || exit 1
konanc -target $TARGET opengl $DIR/OpenGlTeapot.kt -nativelibrary openglstubs.bc -linkerArgs "$LINKER_ARGS" -o OpenGlTeapot.kexe || exit 1
# OpenGL stubs are rather big, so we need more heap space.
konanc -J-Xmx2G -target $TARGET opengl $DIR/OpenGlTeapot.kt -nativelibrary openglstubs.bc -linkerArgs "$LINKER_ARGS" -o OpenGlTeapot.kexe || exit 1
+6 -2
View File
@@ -1,2 +1,6 @@
headers = GLUT/glut.h
compilerOpts = -framework OpenGL -framework GLUT
headers =
headers.osx = GLUT/glut.h
headers.linux = GL/glut.h
compilerOpts =
compilerOpts.osx = -framework OpenGL -framework GLUT
compilerOpts.linux = -I/usr/include