Improve samples (#396)
This commit is contained in:
+1
-1
@@ -95,7 +95,7 @@ private fun ProcessBuilder.runExpectingSuccess() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Properties.getSpaceSeparated(name: String): List<String> {
|
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,
|
private fun Properties.getOsSpecific(name: String,
|
||||||
|
|||||||
@@ -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)
|
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.
|
from EU is being used.
|
||||||
|
|
||||||
@@ -10,5 +10,4 @@ To run use
|
|||||||
|
|
||||||
./CsvParser.kexe ./European_Mammals_Red_List_Nov_2009.csv 4 100
|
./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
|
It will print fifth column (Family, zero-based index) in first 100 rows of the CSV file.
|
||||||
CSV 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.
|
||||||
Executable
+27
@@ -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
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
headers = git2.h
|
||||||
|
linkerOpts = -lgit2
|
||||||
|
excludedFunctions =
|
||||||
@@ -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()
|
||||||
|
})
|
||||||
@@ -4,7 +4,7 @@ PATH=../../dist/bin:../../bin:$PATH
|
|||||||
DIR=.
|
DIR=.
|
||||||
|
|
||||||
LINKER_ARGS_macbook="-framework OpenGL -framework GLUT"
|
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
|
if [ x$TARGET == x ]; then
|
||||||
case "$OSTYPE" in
|
case "$OSTYPE" in
|
||||||
@@ -22,4 +22,5 @@ var=COMPILER_ARGS_${TARGET}
|
|||||||
COMPILER_ARGS=${!var} # add -opt for an optimized build.
|
COMPILER_ARGS=${!var} # add -opt for an optimized build.
|
||||||
|
|
||||||
interop -def:$DIR/opengl.def -target:$TARGET || exit 1
|
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
|
||||||
|
|||||||
@@ -1,2 +1,6 @@
|
|||||||
headers = GLUT/glut.h
|
headers =
|
||||||
compilerOpts = -framework OpenGL -framework GLUT
|
headers.osx = GLUT/glut.h
|
||||||
|
headers.linux = GL/glut.h
|
||||||
|
compilerOpts =
|
||||||
|
compilerOpts.osx = -framework OpenGL -framework GLUT
|
||||||
|
compilerOpts.linux = -I/usr/include
|
||||||
|
|||||||
Reference in New Issue
Block a user