feat(repo): added minimal repo class

This commit is contained in:
darwincereska
2025-11-06 11:23:40 -05:00
parent 51f3361bef
commit 9778ad6647
6 changed files with 187 additions and 9 deletions

View File

@@ -2,12 +2,12 @@
- [x] Initialize Project
- [x] Configure `build.gradle.kts` with dependencies
- [ ] Set up testing framework
- [x] Set up testing framework
# Core
- [ ] Create `Repository.kt` class
- [ ] Implement `.notevc` directory initialization
- [x] Create `Repository.kt` class
- [x] Implement `.notevc` directory initialization
- [ ] Create `ObjectStore.kt` for content storage
- [ ] Implement content hashing `HashUtils.kt`
- [ ] Create `NoteSnapshot` data class

View File

@@ -1,25 +1,48 @@
import java.time.Instant
plugins {
kotlin("jvm") version "2.2.21"
kotlin("plugin.serialization") version "2.2.21"
application
id("com.github.gmazzo.buildconfig") version "4.1.2"
id("com.gradleup.shadow") version "9.2.2"
}
group = "io.notevc"
version = "1.0.0"
buildConfig {
buildConfigField("String", "VERSION", "\"${project.version}\"")
buildConfigField("String", "BUILD_TIME", "\"${Instant.now()}\"")
packageName("io.notevc")
}
repositories {
mavenCentral()
}
dependencies {
val junitVersion = "5.10.0"
implementation(kotlin("stdlib"))
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")
testImplementation("org.junit.jupiter:junit-jupiter-api:$junitVersion")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:$junitVersion")
}
application {
mainClass.set("io.notevc.NoteVCKt")
}
tasks.jar {
manifest {
attributes["Main-Class"] = "io.notevc.NoteVCKt"
}
tasks.withType<Test> {
useJUnitPlatform()
}
tasks.build {
dependsOn(tasks.shadowJar)
}
tasks.jar {
enabled = false
}

View File

@@ -1,5 +1,31 @@
package io.notevc
fun main() {
println("hello world")
import io.notevc.core.Repository
import io.notevc.commands.*
fun main(args: Array<String>) {
// Args logic
when (args.firstOrNull()) {
"init" -> {
val initCommand = InitCommand()
val result = initCommand.execute(args.getOrNull(1))
result.fold(
onSuccess = { message -> println(message) },
onFailure = { error -> println("Error: ${error.message}") }
)
}
"commit" -> {
println("Not implemented yet")
}
"status" -> {
println("Not implemented yet")
}
"version", "--version", "-v" -> {
println("notevc version ${Repository.VERSION}")
}
}
}

View File

@@ -1 +1,26 @@
package io.notevc.commands
import io.notevc.core.Repository
import java.nio.file.Path
class InitCommand {
fun execute(path: String?): Result<String> {
return try {
val repo = if (path != null) {
Repository.at(path).getOrElse { return Result.failure(it) }
} else Repository.current()
repo.init().fold(
onSuccess = {
Result.success("Initialized notevc repository in ${repo.path.toAbsolutePath()}")
},
onFailure = {
error -> Result.failure(error)
}
)
}
catch (e: Exception) {
Result.failure(e)
}
}
}

View File

@@ -1 +1,103 @@
package io.notevc.core
import java.nio.file.Path
import java.nio.file.Paths
import kotlin.io.path.*
import io.notevc.BuildConfig
import kotlinx.serialization.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.encodeToString
import java.nio.file.Files
import java.time.Instant
class Repository private constructor(private val rootPath: Path) {
private val notevcDir = rootPath.resolve(NOTEVC_DIR)
val path: Path get() = rootPath
val isInitialized: Boolean get() = notevcDir.exists()
companion object {
// Factory methods - these create Repository instances
// Create repository at a specified path
fun at(path: String): Result<Repository> {
return try {
val absolutePath = Path.of(path).toAbsolutePath()
when {
!absolutePath.exists() -> Result.failure(Exception("Directory does not exist: $path"))
!absolutePath.isDirectory() -> Result.failure(Exception("Path is not directory: $path"))
!absolutePath.isWritable() -> Result.failure(Exception("Directory is not writable: $path"))
else -> Result.success(Repository(absolutePath))
}
}
catch (e: Exception) {
Result.failure(e)
}
}
// Create repository at current directory
fun current(): Repository = Repository(Path.of(System.getProperty("user.dir")).toAbsolutePath())
// Find existing repository by walking up
fun find(): Repository? {
var current = Path.of(System.getProperty("user.dir")).toAbsolutePath()
while (current != null) {
if (current.resolve(NOTEVC_DIR).exists()) return Repository(current)
current = current.parent // Go up one level
}
return null // No repository found
}
// Constants
const val NOTEVC_DIR = ".notevc"
val VERSION = BuildConfig.VERSION
val BUILD_TIME = BuildConfig.BUILD_TIME
}
override fun toString(): String = "Repository(path=${rootPath.toAbsolutePath()}, initialized=$isInitialized)"
fun init(): Result<Unit> {
return try {
// Check if already initialized
if (isInitialized) return Result.failure(Exception("Repository already initialized at ${rootPath.toAbsolutePath()}"))
// Create .notevc directory structure
Files.createDirectories(notevcDir)
Files.createDirectories(notevcDir.resolve("objects"))
// Create initial metadata
val metadata = RepoMetadata(
version = VERSION,
created = Instant.now().toString(),
head = null
)
// Save metadata to .notevc/metadata.json
val metadataFile = notevcDir.resolve("metadata.json")
Files.writeString(metadataFile, Json.encodeToString(metadata))
// Create empty timeline
val timelineFile = notevcDir.resolve("timeline.json")
Files.writeString(timelineFile, "[]")
Result.success(Unit)
}
catch (e: Exception) {
Result.failure(e)
}
}
}
@Serializable
data class RepoMetadata(
val version: String,
val created: String,
var head: String?
)
@Serializable
data class RepoConfig(
val autoCommit: Boolean = false,
val compressionEnabled: Boolean = false,
val maxSnapshots: Int = 100
)

View File

@@ -1 +1,3 @@
package io.notevc.utils