diff --git a/cli/internal/ffi/ffi.go b/cli/internal/ffi/ffi.go index 499e2c04ee846..7ac15e45ff59e 100644 --- a/cli/internal/ffi/ffi.go +++ b/cli/internal/ffi/ffi.go @@ -116,15 +116,15 @@ func stringToRef(s string) *string { } // ChangedFiles returns the files changed in between two commits, the workdir and the index, and optionally untracked files -func ChangedFiles(repoRoot string, monorepoRoot string, fromCommit string, toCommit string) ([]string, error) { +func ChangedFiles(gitRoot string, turboRoot string, fromCommit string, toCommit string) ([]string, error) { fromCommitRef := stringToRef(fromCommit) toCommitRef := stringToRef(toCommit) req := ffi_proto.ChangedFilesReq{ - RepoRoot: repoRoot, - FromCommit: fromCommitRef, - ToCommit: toCommitRef, - MonorepoRoot: monorepoRoot, + GitRoot: gitRoot, + FromCommit: fromCommitRef, + ToCommit: toCommitRef, + TurboRoot: turboRoot, } reqBuf := Marshal(&req) @@ -144,9 +144,9 @@ func ChangedFiles(repoRoot string, monorepoRoot string, fromCommit string, toCom } // PreviousContent returns the content of a file at a previous commit -func PreviousContent(repoRoot, fromCommit, filePath string) ([]byte, error) { +func PreviousContent(gitRoot, fromCommit, filePath string) ([]byte, error) { req := ffi_proto.PreviousContentReq{ - RepoRoot: repoRoot, + GitRoot: gitRoot, FromCommit: fromCommit, FilePath: filePath, } diff --git a/cli/internal/ffi/proto/messages.pb.go b/cli/internal/ffi/proto/messages.pb.go index 2f505dca23274..22992d32663a5 100644 --- a/cli/internal/ffi/proto/messages.pb.go +++ b/cli/internal/ffi/proto/messages.pb.go @@ -270,10 +270,10 @@ type ChangedFilesReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - RepoRoot string `protobuf:"bytes,1,opt,name=repo_root,json=repoRoot,proto3" json:"repo_root,omitempty"` - MonorepoRoot string `protobuf:"bytes,2,opt,name=monorepo_root,json=monorepoRoot,proto3" json:"monorepo_root,omitempty"` - FromCommit *string `protobuf:"bytes,3,opt,name=from_commit,json=fromCommit,proto3,oneof" json:"from_commit,omitempty"` - ToCommit *string `protobuf:"bytes,4,opt,name=to_commit,json=toCommit,proto3,oneof" json:"to_commit,omitempty"` + GitRoot string `protobuf:"bytes,1,opt,name=git_root,json=gitRoot,proto3" json:"git_root,omitempty"` + TurboRoot string `protobuf:"bytes,2,opt,name=turbo_root,json=turboRoot,proto3" json:"turbo_root,omitempty"` + FromCommit *string `protobuf:"bytes,3,opt,name=from_commit,json=fromCommit,proto3,oneof" json:"from_commit,omitempty"` + ToCommit *string `protobuf:"bytes,4,opt,name=to_commit,json=toCommit,proto3,oneof" json:"to_commit,omitempty"` } func (x *ChangedFilesReq) Reset() { @@ -308,16 +308,16 @@ func (*ChangedFilesReq) Descriptor() ([]byte, []int) { return file_turborepo_ffi_messages_proto_rawDescGZIP(), []int{4} } -func (x *ChangedFilesReq) GetRepoRoot() string { +func (x *ChangedFilesReq) GetGitRoot() string { if x != nil { - return x.RepoRoot + return x.GitRoot } return "" } -func (x *ChangedFilesReq) GetMonorepoRoot() string { +func (x *ChangedFilesReq) GetTurboRoot() string { if x != nil { - return x.MonorepoRoot + return x.TurboRoot } return "" } @@ -468,7 +468,7 @@ type PreviousContentReq struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - RepoRoot string `protobuf:"bytes,1,opt,name=repo_root,json=repoRoot,proto3" json:"repo_root,omitempty"` + GitRoot string `protobuf:"bytes,1,opt,name=git_root,json=gitRoot,proto3" json:"git_root,omitempty"` FromCommit string `protobuf:"bytes,2,opt,name=from_commit,json=fromCommit,proto3" json:"from_commit,omitempty"` FilePath string `protobuf:"bytes,3,opt,name=file_path,json=filePath,proto3" json:"file_path,omitempty"` } @@ -505,9 +505,9 @@ func (*PreviousContentReq) Descriptor() ([]byte, []int) { return file_turborepo_ffi_messages_proto_rawDescGZIP(), []int{7} } -func (x *PreviousContentReq) GetRepoRoot() string { +func (x *PreviousContentReq) GetGitRoot() string { if x != nil { - return x.RepoRoot + return x.GitRoot } return "" } @@ -1027,84 +1027,84 @@ var file_turborepo_ffi_messages_proto_rawDesc = []byte{ 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x0a, 0x0c, 0x47, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x73, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, - 0xb9, 0x01, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x12, 0x1b, 0x0a, 0x09, 0x72, 0x65, 0x70, 0x6f, 0x5f, 0x72, 0x6f, 0x6f, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6f, 0x52, 0x6f, 0x6f, 0x74, - 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x6f, 0x6e, 0x6f, 0x72, 0x65, 0x70, 0x6f, 0x5f, 0x72, 0x6f, 0x6f, - 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6d, 0x6f, 0x6e, 0x6f, 0x72, 0x65, 0x70, - 0x6f, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x24, 0x0a, 0x0b, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x66, 0x72, - 0x6f, 0x6d, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x74, - 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, - 0x52, 0x08, 0x74, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, - 0x0c, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x42, 0x0c, 0x0a, - 0x0a, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x22, 0x61, 0x0a, 0x10, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, - 0x29, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, - 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x4c, 0x69, 0x73, - 0x74, 0x48, 0x00, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x72, + 0xb1, 0x01, 0x0a, 0x0f, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1d, + 0x0a, 0x0a, 0x74, 0x75, 0x72, 0x62, 0x6f, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x74, 0x75, 0x72, 0x62, 0x6f, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x24, 0x0a, + 0x0b, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x66, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x08, 0x74, 0x6f, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x74, 0x6f, 0x5f, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x22, 0x61, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x46, 0x69, + 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x29, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, + 0x46, 0x69, 0x6c, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x66, 0x69, 0x6c, + 0x65, 0x73, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, + 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, + 0x22, 0x6d, 0x0a, 0x12, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x19, 0x0a, 0x08, 0x67, 0x69, 0x74, 0x5f, 0x72, 0x6f, + 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x67, 0x69, 0x74, 0x52, 0x6f, 0x6f, + 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x66, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x22, + 0x55, 0x0a, 0x13, 0x50, 0x72, 0x65, 0x76, 0x69, 0x6f, 0x75, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x1a, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xf0, 0x01, 0x0a, 0x15, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x69, 0x74, 0x69, 0x76, 0x65, 0x44, 0x65, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x23, 0x0a, 0x0d, + 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x44, 0x69, + 0x72, 0x12, 0x53, 0x0a, 0x0f, 0x75, 0x6e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x5f, + 0x64, 0x65, 0x70, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x44, 0x65, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x2e, 0x55, 0x6e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x44, 0x65, 0x70, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x75, 0x6e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, + 0x65, 0x64, 0x44, 0x65, 0x70, 0x73, 0x1a, 0x41, 0x0a, 0x13, 0x55, 0x6e, 0x72, 0x65, 0x73, 0x6f, + 0x6c, 0x76, 0x65, 0x64, 0x44, 0x65, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x70, 0x0a, 0x16, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x44, 0x65, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x4c, 0x6f, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, + 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x08, 0x70, + 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, + 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x53, 0x0a, 0x0f, 0x4c, + 0x6f, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, + 0x75, 0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x75, 0x6e, 0x64, + 0x22, 0x3b, 0x0a, 0x13, 0x4c, 0x6f, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x63, 0x6b, + 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x4c, 0x6f, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, + 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x69, 0x0a, + 0x0f, 0x53, 0x75, 0x62, 0x67, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0a, + 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, + 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, + 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x22, 0x54, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x67, + 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x08, + 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, + 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, - 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x4c, 0x69, - 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x6f, 0x0a, 0x12, 0x50, 0x72, 0x65, 0x76, - 0x69, 0x6f, 0x75, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x1b, - 0x0a, 0x09, 0x72, 0x65, 0x70, 0x6f, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x72, 0x65, 0x70, 0x6f, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x66, - 0x72, 0x6f, 0x6d, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x66, 0x72, 0x6f, 0x6d, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1b, 0x0a, 0x09, - 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x22, 0x55, 0x0a, 0x13, 0x50, 0x72, 0x65, - 0x76, 0x69, 0x6f, 0x75, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x12, 0x1a, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0c, 0x48, 0x00, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x05, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0xf0, 0x01, 0x0a, 0x15, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x44, - 0x65, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x77, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x44, 0x69, 0x72, 0x12, 0x53, 0x0a, 0x0f, 0x75, - 0x6e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x5f, 0x64, 0x65, 0x70, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x44, 0x65, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x55, 0x6e, 0x72, - 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x44, 0x65, 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x0e, 0x75, 0x6e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x44, 0x65, 0x70, 0x73, - 0x1a, 0x41, 0x0a, 0x13, 0x55, 0x6e, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x44, 0x65, - 0x70, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, - 0x02, 0x38, 0x01, 0x22, 0x70, 0x0a, 0x16, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x76, - 0x65, 0x44, 0x65, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x32, 0x0a, - 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x14, 0x2e, 0x4c, 0x6f, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, - 0x73, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x53, 0x0a, 0x0f, 0x4c, 0x6f, 0x63, 0x6b, 0x66, 0x69, 0x6c, - 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x22, 0x3b, 0x0a, 0x13, 0x4c, 0x6f, - 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x24, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x10, 0x2e, 0x4c, 0x6f, 0x63, 0x6b, 0x66, 0x69, 0x6c, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x69, 0x0a, 0x0f, 0x53, 0x75, 0x62, 0x67, 0x72, - 0x61, 0x70, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6f, - 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x77, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, - 0x65, 0x73, 0x22, 0x54, 0x0a, 0x10, 0x53, 0x75, 0x62, 0x67, 0x72, 0x61, 0x70, 0x68, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x08, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x08, 0x63, 0x6f, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x73, 0x12, 0x16, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x42, 0x0a, 0x0a, 0x08, - 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0b, 0x5a, 0x09, 0x66, 0x66, 0x69, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x72, 0x42, 0x0a, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x0b, + 0x5a, 0x09, 0x66, 0x66, 0x69, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/cli/internal/scm/git_go.go b/cli/internal/scm/git_go.go index f3decd8a5237e..0dac2bfdb074b 100644 --- a/cli/internal/scm/git_go.go +++ b/cli/internal/scm/git_go.go @@ -1,3 +1,6 @@ +//go:build go || !rust +// +build go !rust + // Package scm abstracts operations on various tools like git // Currently, only git is supported. // @@ -8,6 +11,7 @@ package scm import ( "fmt" + "github.com/vercel/turbo/cli/internal/turbopath" "os/exec" "path/filepath" "strings" @@ -17,13 +21,13 @@ import ( // git implements operations on a git repository. type git struct { - repoRoot string + repoRoot turbopath.AbsoluteSystemPath } // ChangedFiles returns a list of modified files since the given commit, optionally including untracked files. func (g *git) ChangedFiles(fromCommit string, toCommit string, relativeTo string) ([]string, error) { if relativeTo == "" { - relativeTo = g.repoRoot + relativeTo = g.repoRoot.ToString() } relSuffix := []string{"--", relativeTo} command := []string{"diff", "--name-only", toCommit} diff --git a/cli/internal/scm/git_rust.go b/cli/internal/scm/git_rust.go new file mode 100644 index 0000000000000..4b4cd2dedc1b0 --- /dev/null +++ b/cli/internal/scm/git_rust.go @@ -0,0 +1,34 @@ +// Package scm abstracts operations on various tools like git +// Currently, only git is supported. +// +// Adapted from https://github.com/thought-machine/please/tree/master/src/scm +// Copyright Thought Machine, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +//go:build rust +// +build rust + +package scm + +import ( + "fmt" + "github.com/vercel/turbo/cli/internal/ffi" + "github.com/vercel/turbo/cli/internal/turbopath" +) + +// git implements operations on a git repository. +type git struct { + repoRoot turbopath.AbsoluteSystemPath +} + +// ChangedFiles returns a list of modified files since the given commit, optionally including untracked files. +func (g *git) ChangedFiles(fromCommit string, toCommit string, monorepoRoot string) ([]string, error) { + return ffi.ChangedFiles(g.repoRoot.ToString(), monorepoRoot, fromCommit, toCommit) +} + +func (g *git) PreviousContent(fromCommit string, filePath string) ([]byte, error) { + if fromCommit == "" { + return nil, fmt.Errorf("Need commit sha to inspect file contents") + } + + return ffi.PreviousContent(g.repoRoot.ToString(), fromCommit, filePath) +} diff --git a/cli/internal/scm/scm.go b/cli/internal/scm/scm.go index b491cd8d382ff..e7f17c8b7374a 100644 --- a/cli/internal/scm/scm.go +++ b/cli/internal/scm/scm.go @@ -7,11 +7,8 @@ package scm import ( - "path/filepath" - "github.com/pkg/errors" - "github.com/vercel/turbo/cli/internal/fs" "github.com/vercel/turbo/cli/internal/turbopath" ) @@ -27,8 +24,8 @@ type SCM interface { // newGitSCM returns a new SCM instance for this repo root. // It returns nil if there is no known implementation there. -func newGitSCM(repoRoot string) SCM { - if fs.PathExists(filepath.Join(repoRoot, ".git")) { +func newGitSCM(repoRoot turbopath.AbsoluteSystemPath) SCM { + if repoRoot.UntypedJoin(".git").Exists() { return &git{repoRoot: repoRoot} } return nil @@ -36,7 +33,7 @@ func newGitSCM(repoRoot string) SCM { // newFallback returns a new SCM instance for this repo root. // If there is no known implementation it returns a stub. -func newFallback(repoRoot string) (SCM, error) { +func newFallback(repoRoot turbopath.AbsoluteSystemPath) (SCM, error) { if scm := newGitSCM(repoRoot); scm != nil { return scm, nil } @@ -52,5 +49,5 @@ func FromInRepo(repoRoot turbopath.AbsoluteSystemPath) (SCM, error) { if err != nil { return nil, err } - return newFallback(dotGitDir.Dir().ToStringDuringMigration()) + return newFallback(dotGitDir.Dir()) } diff --git a/crates/turborepo-ffi/messages.proto b/crates/turborepo-ffi/messages.proto index 40d7214b225a3..8749d3b9b527d 100644 --- a/crates/turborepo-ffi/messages.proto +++ b/crates/turborepo-ffi/messages.proto @@ -24,10 +24,10 @@ message GlobRespList { } message ChangedFilesReq { - string repo_root = 1; - string monorepo_root = 2; + string git_root = 1; + string turbo_root = 2; optional string from_commit = 3; - optional string to_commit = 4; + string to_commit = 4; } message ChangedFilesResp { @@ -42,7 +42,7 @@ message ChangedFilesList { } message PreviousContentReq { - string repo_root = 1; + string git_root = 1; string from_commit = 2; string file_path = 3; } diff --git a/crates/turborepo-ffi/src/lib.rs b/crates/turborepo-ffi/src/lib.rs index 00c95e420bc92..a44fca4761693 100644 --- a/crates/turborepo-ffi/src/lib.rs +++ b/crates/turborepo-ffi/src/lib.rs @@ -74,11 +74,11 @@ pub extern "C" fn changed_files(buffer: Buffer) -> Buffer { } }; - let commit_range = req.from_commit.as_deref().zip(req.to_commit.as_deref()); let response = match turborepo_scm::git::changed_files( - req.repo_root.into(), - req.monorepo_root.into(), - commit_range, + req.git_root.into(), + req.turbo_root.into(), + req.from_commit.as_deref(), + &req.to_commit, ) { Ok(files) => { let files: Vec<_> = files.into_iter().collect(); @@ -108,7 +108,7 @@ pub extern "C" fn previous_content(buffer: Buffer) -> Buffer { }; let response = match turborepo_scm::git::previous_content( - req.repo_root.into(), + req.git_root.into(), &req.from_commit, PathBuf::from(req.file_path), ) { diff --git a/crates/turborepo-scm/src/git.rs b/crates/turborepo-scm/src/git.rs index f59a6e674d4b7..a4686f00ecf75 100644 --- a/crates/turborepo-scm/src/git.rs +++ b/crates/turborepo-scm/src/git.rs @@ -1,13 +1,21 @@ -use std::{collections::HashSet, path::PathBuf}; +use std::{ + backtrace::Backtrace, + collections::HashSet, + path::{Path, PathBuf}, + process::Command, +}; -use git2::{DiffFormat, DiffOptions, Repository}; use turbopath::{AbsoluteSystemPathBuf, AnchoredSystemPathBuf}; use crate::Error; /// Finds the changed files in a repository between index and working directory /// (unstaged changes) and between two commits. Includes untracked files, -/// i.e. files not yet in git +/// i.e. files not yet in git. +/// +/// We shell out to git instead of using a git2 library because git2 doesn't +/// support shallow clones, and therefore errors on repositories that +/// are shallow cloned. /// /// # Arguments /// @@ -21,91 +29,100 @@ use crate::Error; pub fn changed_files( git_root: PathBuf, turbo_root: PathBuf, - commit_range: Option<(&str, &str)>, + from_commit: Option<&str>, + to_commit: &str, ) -> Result, Error> { - // Initialize repository at repo root - let repo = Repository::open(&git_root)?; let git_root = AbsoluteSystemPathBuf::new(git_root)?; let turbo_root = AbsoluteSystemPathBuf::new(turbo_root)?; + let turbo_root_relative_to_git_root = git_root.anchor(&turbo_root)?; + let pathspec = turbo_root_relative_to_git_root.to_str()?; let mut files = HashSet::new(); - add_changed_files_from_unstaged_changes(&git_root, &repo, &turbo_root, &mut files)?; - if let Some((from_commit, to_commit)) = commit_range { - add_changed_files_from_commits( + let output = execute_git_command(&git_root, &["diff", "--name-only", to_commit], pathspec)?; + + add_files_from_stdout(&mut files, &git_root, &turbo_root, output); + + if let Some(from_commit) = from_commit { + let output = execute_git_command( &git_root, - &repo, - &turbo_root, - &mut files, - from_commit, - to_commit, + &[ + "diff", + "--name-only", + &format!("{}...{}", from_commit, to_commit), + ], + pathspec, )?; + + add_files_from_stdout(&mut files, &git_root, &turbo_root, output); } + let output = execute_git_command( + &git_root, + &["ls-files", "--others", "--exclude-standard"], + pathspec, + )?; + + add_files_from_stdout(&mut files, &git_root, &turbo_root, output); + Ok(files) } -fn add_changed_files_from_unstaged_changes( - repo_root: &AbsoluteSystemPathBuf, - repo: &Repository, - turbo_root: &AbsoluteSystemPathBuf, - files: &mut HashSet, -) -> Result<(), Error> { - let mut options = DiffOptions::new(); - options.include_untracked(true); - options.recurse_untracked_dirs(true); - - let anchored_turbo_root = repo_root.anchor(turbo_root)?; - options.pathspec(anchored_turbo_root.to_str()?.to_string()); - - let diff = repo.diff_index_to_workdir(None, Some(&mut options))?; - - for delta in diff.deltas() { - let file = delta.old_file(); - if let Some(file_path) = file.path() { - let anchored_to_repo_root_file_path: AnchoredSystemPathBuf = file_path.try_into()?; - let absolute_file_path = repo_root.resolve(&anchored_to_repo_root_file_path); - let anchored_to_turbo_root_file_path = turbo_root.anchor(&absolute_file_path)?; - files.insert(anchored_to_turbo_root_file_path.to_str()?.to_string()); - } +fn execute_git_command( + git_root: &AbsoluteSystemPathBuf, + args: &[&str], + pathspec: &str, +) -> Result, Error> { + let mut command = Command::new("git"); + command.args(args).current_dir(&git_root); + + add_pathspec(&mut command, pathspec); + + let output = command.output()?; + + if !output.status.success() { + let stderr = String::from_utf8(output.stderr).unwrap(); + Err(Error::Git(stderr, Backtrace::capture())) + } else { + Ok(output.stdout) } +} - Ok(()) +fn add_pathspec(command: &mut Command, pathspec: &str) { + if pathspec != "" { + command.arg("--").arg(pathspec); + } } -fn add_changed_files_from_commits( - repo_root: &AbsoluteSystemPathBuf, - repo: &Repository, - turbo_root: &AbsoluteSystemPathBuf, +fn add_files_from_stdout( files: &mut HashSet, - from_commit: &str, - to_commit: &str, -) -> Result<(), Error> { - let from_commit_ref = repo.revparse_single(from_commit)?; - let to_commit_ref = repo.revparse_single(to_commit)?; - let from_commit = from_commit_ref.peel_to_commit()?; - let to_commit = to_commit_ref.peel_to_commit()?; - let from_tree = from_commit.tree()?; - let to_tree = to_commit.tree()?; - - let mut options = DiffOptions::new(); - let anchored_turbo_root = repo_root.anchor(turbo_root)?; - options.pathspec(anchored_turbo_root.to_str()?); - - let diff = repo.diff_tree_to_tree(Some(&from_tree), Some(&to_tree), Some(&mut options))?; - diff.print(DiffFormat::NameOnly, |_, _, _| true)?; - - for delta in diff.deltas() { - let file = delta.old_file(); - if let Some(file_path) = file.path() { - let anchored_to_repo_root_file_path: AnchoredSystemPathBuf = file_path.try_into()?; - let absolute_file_path = repo_root.resolve(&anchored_to_repo_root_file_path); - let anchored_to_turbo_root_file_path = turbo_root.anchor(&absolute_file_path)?; - files.insert(anchored_to_turbo_root_file_path.to_str()?.to_string()); - } + git_root: &AbsoluteSystemPathBuf, + turbo_root: &AbsoluteSystemPathBuf, + stdout: Vec, +) { + let stdout = String::from_utf8(stdout).unwrap(); + for line in stdout.lines() { + let path = Path::new(line); + let anchored_to_turbo_root_file_path = + reanchor_path_from_git_root_to_turbo_root(git_root, turbo_root, path).unwrap(); + files.insert( + anchored_to_turbo_root_file_path + .to_str() + .unwrap() + .to_string(), + ); } +} - Ok(()) +fn reanchor_path_from_git_root_to_turbo_root( + git_root: &AbsoluteSystemPathBuf, + turbo_root: &AbsoluteSystemPathBuf, + path: &Path, +) -> Result { + let anchored_to_git_root_file_path: AnchoredSystemPathBuf = path.try_into()?; + let absolute_file_path = git_root.resolve(&anchored_to_git_root_file_path); + let anchored_to_turbo_root_file_path = turbo_root.anchor(&absolute_file_path)?; + Ok(anchored_to_turbo_root_file_path) } /// Finds the content of a file at a previous commit. Assumes file is in a git @@ -113,45 +130,75 @@ fn add_changed_files_from_commits( /// /// # Arguments /// -/// * `repo_root`: The root of the repository +/// * `git_root`: The root of the repository /// * `from_commit`: The commit hash to checkout /// * `file_path`: The path to the file /// /// returns: Result pub fn previous_content( - repo_root: PathBuf, + git_root: PathBuf, from_commit: &str, file_path: PathBuf, ) -> Result, Error> { - let repo = Repository::open(&repo_root)?; - let repo_root = AbsoluteSystemPathBuf::new(dunce::canonicalize(repo_root)?)?; - let file_path = AbsoluteSystemPathBuf::new(dunce::canonicalize(file_path)?)?; - let from_commit_ref = repo.revparse_single(from_commit)?; - let from_commit = from_commit_ref.peel_to_commit()?; - let from_tree = from_commit.tree()?; - - let relative_path = repo_root.anchor(&file_path)?; + // If git root is not absolute, we error. + let git_root = AbsoluteSystemPathBuf::new(git_root)?; - let file = from_tree.get_path(relative_path.as_path())?; - let blob = repo.find_blob(file.id())?; - let content = blob.content(); + // However for file path we handle both absolute and relative paths + // Note that we assume any relative file path is relative to the git root + let anchored_file_path = if file_path.is_absolute() { + let absolute_file_path = AbsoluteSystemPathBuf::new(file_path)?; + git_root.anchor(&absolute_file_path)? + } else { + file_path.as_path().try_into()? + }; - Ok(content.to_vec()) + let mut command = Command::new("git"); + let command = command + .arg("show") + .arg(format!( + "{}:{}", + from_commit, + anchored_file_path.to_str().unwrap() + )) + .current_dir(&git_root); + + let output = command.output()?; + if output.status.success() { + Ok(output.stdout) + } else { + Err(Error::Git( + String::from_utf8_lossy(&output.stderr).to_string(), + Backtrace::capture(), + )) + } } #[cfg(test)] mod tests { use std::{ + assert_matches::assert_matches, collections::HashSet, - env::set_current_dir, fs, path::{Path, PathBuf}, + process::Command, }; use git2::{Oid, Repository}; + use tempfile::TempDir; + use turbopath::PathValidationError; use super::previous_content; - use crate::Error; + use crate::{git::changed_files, Error}; + + fn setup_repository() -> Result<(TempDir, Repository), Error> { + let repo_root = tempfile::tempdir()?; + let repo = Repository::init(repo_root.path())?; + let mut config = repo.config()?; + config.set_str("user.name", "test")?; + config.set_str("user.email", "test@example.com")?; + + Ok((repo_root, repo)) + } fn commit_file( repo: &Repository, @@ -181,14 +228,129 @@ mod tests { )?) } + fn commit_delete(repo: &Repository, path: &Path, previous_commit: Oid) -> Result { + let mut index = repo.index()?; + index.remove_path(path)?; + let tree_oid = index.write_tree()?; + index.write()?; + let tree = repo.find_tree(tree_oid)?; + let previous_commit = repo.find_commit(previous_commit)?; + + Ok(repo.commit( + Some("HEAD"), + &repo.signature()?, + &repo.signature()?, + "Commit", + &tree, + std::slice::from_ref(&&previous_commit), + )?) + } + + #[test] + fn test_shallow_clone() -> Result<(), Error> { + let tmp_dir = tempfile::tempdir()?; + let output = Command::new("git") + .args(&[ + "clone", + "--depth", + "2", + "https://github.com/vercel/app-playground.git", + tmp_dir.path().to_str().unwrap(), + ]) + .output()?; + assert!(output.status.success()); + + assert!(changed_files( + tmp_dir.path().to_owned(), + tmp_dir.path().to_owned(), + Some("HEAD~1"), + "HEAD", + ) + .is_ok()); + + assert!(changed_files( + tmp_dir.path().to_owned(), + tmp_dir.path().to_owned(), + None, + "HEAD", + ) + .is_ok()); + + Ok(()) + } + + #[test] + fn test_deleted_files() -> Result<(), Error> { + let (repo_root, repo) = setup_repository()?; + + let file = repo_root.path().join("foo.js"); + let file_path = Path::new("foo.js"); + fs::write(&file, "let z = 0;")?; + + let first_commit_oid = commit_file(&repo, &file_path, None)?; + + fs::remove_file(&file)?; + let _second_commit_oid = commit_delete(&repo, &file_path, first_commit_oid)?; + + let first_commit_sha = first_commit_oid.to_string(); + let git_root = repo_root.path().to_owned(); + let turborepo_root = repo_root.path().to_owned(); + let files = changed_files(git_root, turborepo_root, Some(&first_commit_sha), "HEAD")?; + + assert_eq!(files, HashSet::from(["foo.js".to_string()])); + Ok(()) + } + + #[test] + fn test_merge_base() -> Result<(), Error> { + let (repo_root, repo) = setup_repository()?; + let first_file = repo_root.path().join("foo.js"); + fs::write(&first_file, "let z = 0;")?; + // Create a base commit. This will *not* be the merge base + let first_commit_oid = commit_file(&repo, Path::new("foo.js"), None)?; + + let second_file = repo_root.path().join("bar.js"); + fs::write(&second_file, "let y = 1;")?; + // This commit will be the merge base + let second_commit_oid = commit_file(&repo, Path::new("bar.js"), Some(first_commit_oid))?; + + let third_file = repo_root.path().join("baz.js"); + fs::write(&third_file, "let x = 2;")?; + // Create a first commit off of merge base + let third_commit_oid = commit_file(&repo, Path::new("baz.js"), Some(second_commit_oid))?; + + // Move head back to merge base + repo.set_head_detached(second_commit_oid)?; + let fourth_file = repo_root.path().join("qux.js"); + fs::write(&fourth_file, "let w = 3;")?; + // Create a second commit off of merge base + let fourth_commit_oid = commit_file(&repo, Path::new("qux.js"), Some(second_commit_oid))?; + + repo.set_head_detached(third_commit_oid)?; + let merge_base = repo.merge_base(third_commit_oid, fourth_commit_oid)?; + + assert_eq!(merge_base, second_commit_oid); + + let files = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().to_path_buf(), + Some(&third_commit_oid.to_string()), + &fourth_commit_oid.to_string(), + )?; + + assert_eq!( + files, + HashSet::from(["qux.js".to_string(), "baz.js".to_string()]) + ); + + Ok(()) + } + #[test] fn test_changed_files() -> Result<(), Error> { - let repo_root = tempfile::tempdir()?; - let repo = Repository::init(repo_root.path())?; + let (repo_root, repo) = setup_repository()?; + let mut index = repo.index()?; let turbo_root = repo_root.path(); - let mut config = repo.config()?; - config.set_str("user.name", "test")?; - config.set_str("user.email", "test@example.com")?; let file = repo_root.path().join("foo.js"); fs::write(file, "let z = 0;")?; @@ -200,10 +362,24 @@ mod tests { fs::write(new_file, "let y = 1;")?; // Test that uncommitted file is marked as changed - let files = super::changed_files( + let files = changed_files( + repo_root.path().to_path_buf(), + turbo_root.to_path_buf(), + None, + "HEAD", + )?; + assert_eq!(files, HashSet::from(["bar.js".to_string()])); + + // Add file to index + index.add_path(Path::new("bar.js"))?; + index.write()?; + + // Test that uncommitted file in index is still marked as changed + let files = changed_files( repo_root.path().to_path_buf(), turbo_root.to_path_buf(), None, + "HEAD", )?; assert_eq!(files, HashSet::from(["bar.js".to_string()])); @@ -211,13 +387,11 @@ mod tests { let second_commit_oid = commit_file(&repo, Path::new("bar.js"), Some(first_commit_oid))?; // Test that only second file is marked as changed when we check commit range - let files = super::changed_files( + let files = changed_files( repo_root.path().to_path_buf(), turbo_root.to_path_buf(), - Some(( - first_commit_oid.to_string().as_str(), - second_commit_oid.to_string().as_str(), - )), + Some(first_commit_oid.to_string().as_str()), + second_commit_oid.to_string().as_str(), )?; assert_eq!(files, HashSet::from(["bar.js".to_string()])); @@ -227,13 +401,11 @@ mod tests { fs::write(new_file, "let x = 2;")?; // Test that `turbo_root` filters out files not in the specified directory - let files = super::changed_files( + let files = changed_files( repo_root.path().to_path_buf(), repo_root.path().join("subdir"), - Some(( - first_commit_oid.to_string().as_str(), - second_commit_oid.to_string().as_str(), - )), + Some(first_commit_oid.to_string().as_str()), + second_commit_oid.to_string().as_str(), )?; assert_eq!(files, HashSet::from(["baz.js".to_string()])); @@ -242,11 +414,7 @@ mod tests { #[test] fn test_changed_files_with_root_as_relative() -> Result<(), Error> { - let repo_root = tempfile::tempdir()?; - let repo = Repository::init(repo_root.path())?; - let mut config = repo.config()?; - config.set_str("user.name", "test")?; - config.set_str("user.email", "test@example.com")?; + let (repo_root, repo) = setup_repository()?; let file = repo_root.path().join("foo.js"); fs::write(file, "let z = 0;")?; @@ -259,10 +427,11 @@ mod tests { // Test that uncommitted file is marked as changed with the parameters that Go // will pass - let files = super::changed_files( + let files = changed_files( repo_root.path().to_path_buf(), repo_root.path().to_path_buf(), None, + "HEAD", )?; assert_eq!(files, HashSet::from(["bar.js".to_string()])); @@ -273,11 +442,7 @@ mod tests { // (occurs when the monorepo is nested inside a subdirectory of git repository) #[test] fn test_changed_files_with_subdir_as_turbo_root() -> Result<(), Error> { - let repo_root = tempfile::tempdir()?; - let repo = Repository::init(repo_root.path())?; - let mut config = repo.config()?; - config.set_str("user.name", "test")?; - config.set_str("user.email", "test@example.com")?; + let (repo_root, repo) = setup_repository()?; fs::create_dir(repo_root.path().join("subdir"))?; // Create additional nested directory to test that we return a system path @@ -291,10 +456,11 @@ mod tests { let new_file = repo_root.path().join("subdir").join("src").join("bar.js"); fs::write(new_file, "let y = 1;")?; - let files = super::changed_files( + let files = changed_files( repo_root.path().to_path_buf(), repo_root.path().join("subdir"), None, + "HEAD", )?; #[cfg(unix)] @@ -309,13 +475,11 @@ mod tests { commit_file(&repo, Path::new("subdir/src/bar.js"), Some(first_commit))?; - let files = super::changed_files( + let files = changed_files( repo_root.path().to_path_buf(), repo_root.path().join("subdir"), - Some(( - first_commit.to_string().as_str(), - repo.head()?.peel_to_commit()?.id().to_string().as_str(), - )), + Some(first_commit.to_string().as_str()), + repo.head()?.peel_to_commit()?.id().to_string().as_str(), )?; #[cfg(unix)] @@ -333,11 +497,7 @@ mod tests { #[test] fn test_previous_content() -> Result<(), Error> { - let repo_root = tempfile::tempdir()?; - let repo = Repository::init(repo_root.path())?; - let mut config = repo.config()?; - config.set_str("user.name", "test")?; - config.set_str("user.email", "test@example.com")?; + let (repo_root, repo) = setup_repository()?; let file = repo_root.path().join("foo.js"); fs::write(&file, "let z = 0;")?; @@ -361,20 +521,10 @@ mod tests { )?; assert_eq!(content, b"let z = 1;"); - set_current_dir(repo_root.path())?; - - // Check that relative paths work as well - let content = previous_content( - PathBuf::from("."), - second_commit_oid.to_string().as_str(), - PathBuf::from("./foo.js"), - )?; - assert_eq!(content, b"let z = 1;"); - let content = previous_content( repo_root.path().to_path_buf(), second_commit_oid.to_string().as_str(), - PathBuf::from("./foo.js"), + PathBuf::from("foo.js"), )?; assert_eq!(content, b"let z = 1;"); @@ -383,11 +533,7 @@ mod tests { #[test] fn test_revparse() -> Result<(), Error> { - let repo_root = tempfile::tempdir()?; - let repo = Repository::init(repo_root.path())?; - let mut config = repo.config()?; - config.set_str("user.name", "test")?; - config.set_str("user.email", "test@example.com")?; + let (repo_root, repo) = setup_repository()?; let file = repo_root.path().join("foo.js"); fs::write(&file, "let z = 0;")?; @@ -401,6 +547,77 @@ mod tests { let revparsed_head_minus_1 = repo.revparse_single("HEAD~1")?; assert_eq!(revparsed_head_minus_1.id(), first_commit_oid); + let files = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().to_path_buf(), + Some("HEAD^"), + "HEAD", + )?; + assert_eq!(files, HashSet::from(["foo.js".to_string()])); + + let content = previous_content(repo_root.path().to_path_buf(), "HEAD^", file)?; + assert_eq!(content, b"let z = 0;"); + + let new_file = repo_root.path().join("bar.js"); + fs::write(&new_file, "let y = 0;")?; + let third_commit_oid = commit_file(&repo, Path::new("bar.js"), Some(second_commit_oid))?; + let third_commit = repo.find_commit(third_commit_oid)?; + repo.branch("release-1", &third_commit, false)?; + + let files = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().to_path_buf(), + Some("HEAD~1"), + "release-1", + )?; + assert_eq!(files, HashSet::from(["bar.js".to_string()])); + + Ok(()) + } + + #[test] + fn test_error_cases() -> Result<(), Error> { + let repo_dir = tempfile::tempdir()?; + let repo_does_not_exist = changed_files( + repo_dir.path().to_path_buf(), + repo_dir.path().to_path_buf(), + None, + "HEAD", + ); + + assert_matches!(repo_does_not_exist, Err(Error::Git(_, _))); + + let (repo_root, _repo) = setup_repository()?; + + let commit_does_not_exist = changed_files( + repo_root.path().to_path_buf(), + repo_root.path().to_path_buf(), + None, + "does-not-exist", + ); + + assert_matches!(commit_does_not_exist, Err(Error::Git(_, _))); + + let file_does_not_exist = previous_content( + repo_root.path().to_path_buf(), + "HEAD", + repo_root.path().join("does-not-exist"), + ); + assert_matches!(file_does_not_exist, Err(Error::Git(_, _))); + + let turbo_root = tempfile::tempdir()?; + let turbo_root_is_not_subdir_of_git_root = changed_files( + repo_root.path().to_path_buf(), + turbo_root.path().to_path_buf(), + None, + "HEAD", + ); + + assert_matches!( + turbo_root_is_not_subdir_of_git_root, + Err(Error::Path(PathValidationError::NotParent(_, _), _)) + ); + Ok(()) } } diff --git a/crates/turborepo-scm/src/lib.rs b/crates/turborepo-scm/src/lib.rs index 60456ffe4542d..0f4328f6a5591 100644 --- a/crates/turborepo-scm/src/lib.rs +++ b/crates/turborepo-scm/src/lib.rs @@ -1,3 +1,9 @@ +#![feature(error_generic_member_access)] +#![feature(provide_any)] +#![feature(assert_matches)] + +use std::backtrace; + use thiserror::Error; use turbopath::PathValidationError; @@ -6,11 +12,14 @@ pub mod git; #[derive(Debug, Error)] pub enum Error { #[error("git error: {0}")] - Git(#[from] git2::Error), - #[error("repository not found")] - RepositoryNotFound, + Git2(#[from] git2::Error, #[backtrace] backtrace::Backtrace), + #[error("git error: {0}")] + Git(String, #[backtrace] backtrace::Backtrace), #[error("io error: {0}")] - Io(#[from] std::io::Error), + Io(#[from] std::io::Error, #[backtrace] backtrace::Backtrace), #[error("path error: {0}")] - Path(#[from] PathValidationError), + Path( + #[from] PathValidationError, + #[backtrace] backtrace::Backtrace, + ), }