Files
gitks/proto/repository.proto
zhenyi 939931acad feat(repository): add language statistics analysis feature
- Remove data directory from gitignore to include language data
- Add build script to parse linguist languages.yml and generate static mappings
- Include serde and serde_yml dependencies for YAML parsing
- Add lang_stats module with language detection and statistics calculation
- Generate protobuf definitions for language statistics API endpoints
- Implement GetLanguageStats RPC endpoint in repository server
- Add comprehensive test suite for language statistics functionality
- Include extension and filename based language detection logic
- Implement binary file classification and group resolution features
2026-06-10 13:06:59 +08:00

482 lines
12 KiB
Protocol Buffer

syntax = "proto3";
package gitks;
import "google/protobuf/empty.proto";
import "oid.proto";
// Repository identity used by storage-facing RPCs.
message RepositoryHeader {
// Logical storage shard or disk name.
string storage_name = 1;
// Path relative to the storage root, usually ending in `.git` for bare repos.
string relative_path = 2;
// Optional absolute path for embedded/local deployments.
string storage_path = 3;
}
message Repository {
RepositoryHeader header = 1;
bool bare = 2;
bool empty = 3;
ObjectFormat object_format = 4;
string default_branch = 5;
string git_object_directory = 6;
repeated string git_alternate_object_directories = 7;
}
message RepositoryStatistics {
uint64 size_bytes = 1;
uint64 loose_object_count = 2;
uint64 packed_object_count = 3;
uint64 packfile_count = 4;
uint64 reference_count = 5;
uint64 commit_graph_size_bytes = 6;
uint64 multi_pack_index_size_bytes = 7;
}
message RepositoryConfigEntry {
string key = 1;
repeated string values = 2;
}
message RepositoryObjectFormatRequest {
RepositoryHeader repository = 1;
}
message RepositoryObjectFormatResponse {
ObjectFormat object_format = 1;
}
message GetRepositoryRequest {
RepositoryHeader repository = 1;
}
message InitRepositoryRequest {
RepositoryHeader repository = 1;
bool bare = 2;
ObjectFormat object_format = 3;
string initial_branch = 4;
}
message DeleteRepositoryRequest {
RepositoryHeader repository = 1;
}
message RepositoryExistsRequest {
RepositoryHeader repository = 1;
}
message RepositoryExistsResponse {
bool exists = 1;
}
message GetDefaultBranchRequest {
RepositoryHeader repository = 1;
}
message GetDefaultBranchResponse {
string name = 1;
}
message SetDefaultBranchRequest {
RepositoryHeader repository = 1;
string name = 2;
}
message GetRepositoryConfigRequest {
RepositoryHeader repository = 1;
repeated string keys = 2;
}
message GetRepositoryConfigResponse {
repeated RepositoryConfigEntry entries = 1;
}
message SetRepositoryConfigRequest {
RepositoryHeader repository = 1;
repeated RepositoryConfigEntry entries = 2;
}
message RepositoryStatisticsRequest {
RepositoryHeader repository = 1;
}
message RepositoryHealthRequest {
RepositoryHeader repository = 1;
bool connectivity_only = 2;
}
message RepositoryHealthResponse {
bool ok = 1;
repeated string warnings = 2;
repeated string errors = 3;
RepositoryStatistics statistics = 4;
}
message GarbageCollectRequest {
RepositoryHeader repository = 1;
bool prune = 2;
bool aggressive = 3;
}
message RepackRequest {
RepositoryHeader repository = 1;
bool full = 2;
bool write_bitmaps = 3;
bool write_multi_pack_index = 4;
}
message WriteCommitGraphRequest {
RepositoryHeader repository = 1;
bool replace = 2;
bool split = 3;
}
message RepositoryMaintenanceResponse {
bool ok = 1;
string stdout = 2;
string stderr = 3;
}
message ListHooksRequest {
RepositoryHeader repository = 1;
}
message HookInfo {
string hook_type = 1;
string level = 2; // "server" or "custom"
string path = 3;
}
message ListHooksResponse {
repeated HookInfo hooks = 1;
}
message SetCustomHookRequest {
RepositoryHeader repository = 1;
string hook_name = 2; // "pre-receive", "update", "post-receive"
string content = 3; // Hook script content
}
message RemoveCustomHookRequest {
RepositoryHeader repository = 1;
string hook_name = 2;
}
enum SnapshotStorage {
SNAPSHOT_STORAGE_LOCAL = 0;
SNAPSHOT_STORAGE_S3 = 1;
SNAPSHOT_STORAGE_GCS = 2;
}
message SnapshotInfo {
string snapshot_id = 1;
string relative_path = 2;
uint64 size_bytes = 3;
string created_at = 4; // ISO 8601
string head_oid = 5;
}
message CreateSnapshotRequest {
RepositoryHeader repository = 1;
SnapshotStorage storage = 2;
string storage_path = 3;
}
message CreateSnapshotResponse {
string snapshot_id = 1;
uint64 size_bytes = 2;
string head_oid = 3;
}
message RestoreSnapshotRequest {
RepositoryHeader target_repository = 1;
string snapshot_id = 2;
SnapshotStorage storage = 3;
string storage_path = 4;
}
message ListSnapshotsRequest {
RepositoryHeader repository = 1;
uint32 limit = 2;
}
message ListSnapshotsResponse {
repeated SnapshotInfo snapshots = 1;
}
message DeleteSnapshotRequest {
string snapshot_id = 1;
SnapshotStorage storage = 2;
}
enum MoveRepositoryState {
MOVE_STATE_UNKNOWN = 0;
MOVE_STATE_PREPARING = 1;
MOVE_STATE_TRANSFERRING = 2;
MOVE_STATE_VERIFYING = 3;
MOVE_STATE_COMPLETED = 4;
MOVE_STATE_FAILED = 5;
MOVE_STATE_CANCELLED = 6;
}
message MoveRepositoryRequest {
RepositoryHeader source_repository = 1;
RepositoryHeader target_repository = 2;
}
message MoveRepositoryResponse {
MoveRepositoryState state = 1;
string error_message = 2;
}
message FetchRepositoryDataRequest {
RepositoryHeader repository = 1;
}
message FetchRepositoryDataResponse {
bytes data = 1;
bool done = 2;
}
message FindMergeBaseRequest {
RepositoryHeader repository = 1;
repeated bytes revisions = 2; // hex OIDs to find merge-base for
}
message FindMergeBaseResponse {
string base_oid = 1;
}
message WriteRefRequest {
RepositoryHeader repository = 1;
string ref_name = 2;
string new_oid = 3;
string old_oid = 4; // expected old OID (empty = no check)
bool force = 5;
}
message WriteRefResponse {
bool ok = 1;
string error = 2;
}
message SearchFilesByContentRequest {
RepositoryHeader repository = 1;
string query = 2; // regex pattern
string revision = 3; // tree-ish to search in (default HEAD)
uint32 max_results = 4; // default 100
bool case_sensitive = 5;
}
message SearchFilesByContentResponse {
repeated SearchResult results = 1;
}
message SearchFilesByNameRequest {
RepositoryHeader repository = 1;
string query = 2; // regex pattern for file names
string revision = 3;
uint32 max_results = 4;
bool recursive = 5;
}
message SearchFilesByNameResponse {
repeated SearchResult results = 1;
}
message SearchResult {
string path = 1;
uint32 line = 2; // 0 for name-only search
string matched_text = 3; // the surrounding line content
}
message ObjectsSizeRequest {
RepositoryHeader repository = 1;
repeated string oids = 2;
}
message ObjectsSizeResponse {
repeated ObjectSize sizes = 1;
}
message ObjectSize {
string oid = 1;
uint64 size = 2;
bool found = 3;
}
message RepositorySizeRequest {
RepositoryHeader repository = 1;
}
message RepositorySizeResponse {
uint64 size_bytes = 1;
}
message FindLicenseRequest {
RepositoryHeader repository = 1;
}
message FindLicenseResponse {
string license_spdx = 1; // SPDX identifier, e.g. "MIT"
string license_name = 2; // human-readable name
double confidence = 3; // 0.0 — 1.0
string license_path = 4; // path to LICENSE file
}
enum OptimizeStrategy {
OPTIMIZE_STRATEGY_UNSPECIFIED = 0;
OPTIMIZE_STRATEGY_HEURISTIC = 1; // auto-decide based on repo state
OPTIMIZE_STRATEGY_AGGRESSIVE = 2;
OPTIMIZE_STRATEGY_INCREMENTAL = 3;
}
message OptimizeRepositoryRequest {
RepositoryHeader repository = 1;
OptimizeStrategy strategy = 2;
}
message OptimizeRepositoryResponse {
bool ok = 1;
string stdout = 2;
string stderr = 3;
}
message GetRawChangesRequest {
RepositoryHeader repository = 1;
string base = 2; // revision or OID
string head = 3;
}
message RawChange {
enum Operation {
RAW_CHANGE_OPERATION_UNSPECIFIED = 0;
RAW_CHANGE_OPERATION_ADDED = 1;
RAW_CHANGE_OPERATION_MODIFIED = 2;
RAW_CHANGE_OPERATION_DELETED = 3;
RAW_CHANGE_OPERATION_RENAMED = 4;
RAW_CHANGE_OPERATION_COPIED = 5;
}
Operation operation = 1;
string old_path = 2;
string new_path = 3;
uint32 old_mode = 4;
uint32 new_mode = 5;
string old_oid = 6;
string new_oid = 7;
double similarity = 8;
}
message GetRawChangesResponse {
repeated RawChange changes = 1;
}
message GetLanguageStatsRequest {
RepositoryHeader repository = 1;
ObjectSelector revision = 2; // defaults to HEAD if unset
string path = 3; // optional: restrict to subdirectory
uint32 max_file_size = 4; // skip files larger than this (bytes, 0 = 512KB default)
}
message GetLanguageStatsResponse {
repeated LanguageStat languages = 1;
uint64 total_files = 2;
uint64 total_bytes = 3;
uint64 total_lines = 4;
}
message LanguageStat {
string language = 1; // language name, e.g. "Rust"
string lang_type = 2; // "programming", "markup", "data", "prose"
uint64 file_count = 3;
uint64 bytes = 4;
uint64 lines = 5;
double percentage = 6; // percentage by bytes
}
message FetchRemoteRequest {
RepositoryHeader repository = 1;
string remote_url = 2;
string remote_name = 3; // defaults to "origin"
repeated string refspecs = 4;
bool force = 5;
bool prune = 6;
}
message FetchRemoteResponse {
bool ok = 1;
string error = 2;
}
message CreateRepositoryFromURLRequest {
RepositoryHeader repository = 1;
string remote_url = 2;
bool mirror = 3;
}
message CreateRepositoryFromURLResponse {
Repository repository = 1;
}
service RepositoryService {
rpc GetRepository(GetRepositoryRequest) returns (Repository);
rpc InitRepository(InitRepositoryRequest) returns (Repository);
rpc DeleteRepository(DeleteRepositoryRequest) returns (google.protobuf.Empty);
rpc RepositoryExists(RepositoryExistsRequest) returns (RepositoryExistsResponse);
rpc GetObjectFormat(RepositoryObjectFormatRequest) returns (RepositoryObjectFormatResponse);
rpc GetDefaultBranch(GetDefaultBranchRequest) returns (GetDefaultBranchResponse);
rpc SetDefaultBranch(SetDefaultBranchRequest) returns (google.protobuf.Empty);
rpc GetRepositoryConfig(GetRepositoryConfigRequest) returns (GetRepositoryConfigResponse);
rpc SetRepositoryConfig(SetRepositoryConfigRequest) returns (google.protobuf.Empty);
rpc GetRepositoryStatistics(RepositoryStatisticsRequest) returns (RepositoryStatistics);
rpc CheckRepositoryHealth(RepositoryHealthRequest) returns (RepositoryHealthResponse);
rpc GarbageCollect(GarbageCollectRequest) returns (RepositoryMaintenanceResponse);
rpc Repack(RepackRequest) returns (RepositoryMaintenanceResponse);
rpc WriteCommitGraph(WriteCommitGraphRequest) returns (RepositoryMaintenanceResponse);
// Hooks management
rpc ListHooks(ListHooksRequest) returns (ListHooksResponse);
rpc SetCustomHook(SetCustomHookRequest) returns (google.protobuf.Empty);
rpc RemoveCustomHook(RemoveCustomHookRequest) returns (google.protobuf.Empty);
// Snapshot operations
rpc CreateSnapshot(CreateSnapshotRequest) returns (CreateSnapshotResponse);
rpc RestoreSnapshot(RestoreSnapshotRequest) returns (google.protobuf.Empty);
rpc ListSnapshots(ListSnapshotsRequest) returns (ListSnapshotsResponse);
rpc DeleteSnapshot(DeleteSnapshotRequest) returns (google.protobuf.Empty);
// Repository move
rpc MoveRepository(MoveRepositoryRequest) returns (MoveRepositoryResponse);
rpc FetchRepositoryData(FetchRepositoryDataRequest) returns (stream FetchRepositoryDataResponse);
rpc FindMergeBase(FindMergeBaseRequest) returns (FindMergeBaseResponse);
rpc WriteRef(WriteRefRequest) returns (WriteRefResponse);
rpc SearchFilesByContent(SearchFilesByContentRequest) returns (SearchFilesByContentResponse);
rpc SearchFilesByName(SearchFilesByNameRequest) returns (SearchFilesByNameResponse);
rpc ObjectsSize(ObjectsSizeRequest) returns (ObjectsSizeResponse);
rpc RepositorySize(RepositorySizeRequest) returns (RepositorySizeResponse);
rpc FetchRemote(FetchRemoteRequest) returns (FetchRemoteResponse);
rpc CreateRepositoryFromURL(CreateRepositoryFromURLRequest) returns (CreateRepositoryFromURLResponse);
rpc FindLicense(FindLicenseRequest) returns (FindLicenseResponse);
rpc OptimizeRepository(OptimizeRepositoryRequest) returns (OptimizeRepositoryResponse);
rpc GetRawChanges(GetRawChangesRequest) returns (GetRawChangesResponse);
rpc GetLanguageStats(GetLanguageStatsRequest) returns (GetLanguageStatsResponse);
}