Apply module scope to file validation checks

This commit is contained in:
2026-10-10 02:32:28 +00:00
parent 3a99536f9c
commit 02896b6e12
17 changed files with 308 additions and 79 deletions

View File

@@ -16,6 +16,7 @@ import (
type CandidateTree struct {
context context.Context
repositoryDir string
modulePath string
entries []git.TreeEntry
inputEntries []git.TreeEntry
byPath map[string]int
@@ -53,9 +54,14 @@ func ReadCandidateTreeForScope(ctx context.Context, repositoryDir, commit string
if err != nil {
return nil, err
}
modulePath, err := repositoryModulePath(repositoryDir, scope.ModuleDir)
if err != nil {
return nil, err
}
tree := &CandidateTree{
context: ctx,
repositoryDir: repositoryDir,
modulePath: modulePath,
entries: entries,
byPath: make(map[string]int, len(entries)),
directories: make(map[string]struct{}),
@@ -68,7 +74,7 @@ func ReadCandidateTreeForScope(ctx context.Context, repositoryDir, commit string
tree.directories[directory] = struct{}{}
}
}
tree.inputEntries, err = selectInputEntries(repositoryDir, entries, tree.byPath, scope)
tree.inputEntries, err = selectInputEntries(entries, tree.byPath, modulePath, scope.SharedFiles)
if err != nil {
_ = tree.Close()
return nil, err
@@ -88,34 +94,7 @@ func (tree *CandidateTree) InputEntries() []git.TreeEntry {
return append([]git.TreeEntry(nil), tree.inputEntries...)
}
func selectInputEntries(repositoryDir string, entries []git.TreeEntry, byPath map[string]int, scope TreeScope) ([]git.TreeEntry, error) {
repositoryAbs, err := filepath.Abs(repositoryDir)
if err != nil {
return nil, fmt.Errorf("resolve candidate repository directory: %w", err)
}
moduleDir := scope.ModuleDir
if moduleDir == "" {
moduleDir = repositoryAbs
}
if !filepath.IsAbs(moduleDir) {
return nil, fmt.Errorf("selected module directory must be absolute: %q", moduleDir)
}
moduleAbs, err := filepath.Abs(moduleDir)
if err != nil {
return nil, fmt.Errorf("resolve selected module directory: %w", err)
}
relative, err := filepath.Rel(repositoryAbs, moduleAbs)
if err != nil {
return nil, fmt.Errorf("make selected module relative to repository: %w", err)
}
if relative == ".." || strings.HasPrefix(relative, ".."+string(filepath.Separator)) || filepath.IsAbs(relative) {
return nil, fmt.Errorf("selected module directory %q is outside repository %q", moduleDir, repositoryDir)
}
modulePath := filepath.ToSlash(relative)
if relative == "." {
modulePath = "."
}
func selectInputEntries(entries []git.TreeEntry, byPath map[string]int, modulePath string, sharedFiles []string) ([]git.TreeEntry, error) {
boundaries := make([]string, 0)
for _, entry := range entries {
moduleRelative, ok := relativeToModule(entry.Path, modulePath)
@@ -145,7 +124,6 @@ func selectInputEntries(repositoryDir string, entries []git.TreeEntry, byPath ma
}
}
sharedFiles := scope.SharedFiles
usingDefaults := sharedFiles == nil
if usingDefaults {
sharedFiles = []string{"COPYRIGHT", "LICENSE", "docs/oss/attribution.md"}
@@ -153,14 +131,16 @@ func selectInputEntries(repositoryDir string, entries []git.TreeEntry, byPath ma
for _, requested := range sharedFiles {
name, err := normalizeSharedFile(requested)
if err != nil {
return nil, &Failure{Check: SharedFiles, Findings: []Finding{{Path: requested, Message: err.Error()}}}
cause := fmt.Errorf("invalid shared file path %q: %w", requested, err)
return nil, &Failure{Check: SharedFiles, Findings: []Finding{{Path: requested, Message: cause.Error()}}, Cause: cause}
}
index, exists := byPath[name]
if !exists || entries[index].Type != "blob" {
if usingDefaults {
continue
}
return nil, &Failure{Check: SharedFiles, Findings: []Finding{{Path: name, Message: "selected shared file is not present in the committed tree"}}}
cause := fmt.Errorf("selected shared file %q is not present in the committed tree", name)
return nil, &Failure{Check: SharedFiles, Findings: []Finding{{Path: name, Message: "selected shared file is not present in the committed tree"}}, Cause: cause}
}
selected[name] = entries[index]
}
@@ -177,6 +157,35 @@ func selectInputEntries(repositoryDir string, entries []git.TreeEntry, byPath ma
return inputs, nil
}
func repositoryModulePath(repositoryDir, moduleDir string) (string, error) {
repositoryAbs, err := filepath.Abs(repositoryDir)
if err != nil {
return "", fmt.Errorf("resolve candidate repository directory: %w", err)
}
if moduleDir == "" {
moduleDir = repositoryAbs
}
if !filepath.IsAbs(moduleDir) {
return "", fmt.Errorf("selected module directory must be absolute: %q", moduleDir)
}
moduleAbs, err := filepath.Abs(moduleDir)
if err != nil {
return "", fmt.Errorf("resolve selected module directory: %w", err)
}
relative, err := filepath.Rel(repositoryAbs, moduleAbs)
if err != nil {
return "", fmt.Errorf("make selected module relative to repository: %w", err)
}
if relative == ".." || strings.HasPrefix(relative, ".."+string(filepath.Separator)) || filepath.IsAbs(relative) {
return "", fmt.Errorf("selected module directory %q is outside repository %q", moduleDir, repositoryDir)
}
modulePath := filepath.ToSlash(relative)
if relative == "." {
modulePath = "."
}
return modulePath, nil
}
func relativeToModule(repositoryPath, modulePath string) (string, bool) {
if modulePath == "." {
return repositoryPath, true