-
Notifications
You must be signed in to change notification settings - Fork 213
Export: enhance trimming using build statement metadata #3530
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
DuBento
wants to merge
64
commits into
thought-machine:master
Choose a base branch
from
DuBento:export-from-package-metadata
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
64 commits
Select commit
Hold shift + click to select a range
0ef91bc
Package level metadata that includes a mapping of build statements to…
63f1b0d
export using BuildFileMetadata logic
419bd56
register caller scope for callstack-like traversal
8e1bd00
bufio writer for build statements
258b170
rewrite export logic into explicit flow
4110735
export targets related to build statement
a4252c9
enrich target with subincludes by looping though all scopes
82f117f
separate buildstmt register from adding target
eb657de
select and write subincludes
6535794
skip statement for preloaded subincludes
8e6c9c0
test: trim subincludes
9f0b4fe
rename file
0e597c6
use slices.collect and sort interface
de76e2c
rewrite export with 2 concrete interfaces: default and notrim
03ed361
notrim: full copy BUILD file and visit sources
717aba1
double new lines between targets
94160bf
suppress diff output when enforcing repo differences
582319e
export by filtering the original BUILD file
e6a5293
subincludes use label short string
ea329c3
Simplify package filtering method into a more explicit "switch" case
1a47c22
skip subrepos and internal packages when writing package file
a35119a
fix reusing err var resulted in failed filtering
9c1522c
doc strings for package metadata
9395a59
export missing doc strings
3c3d3d0
test: named go_repo and change testify for slimmer UUID
13e95cb
export dependencies of subrepos - 13/14 tests passing
28b5441
test: internal repo test using temp directory to avoid stale data
781af3a
fix: 0 label subinclude
2f8355c
adjusting dependency lookup and adjacent target test to include secon…
3e89c85
test: add custom tool to native test
9c5af3e
test: go_test export with several deps
922da6f
optional metadata parsing
5aeb360
test: minimal subinclude statement
517486a
collect map keys on active subinclude labels
f8f8e3f
non-fatal warning for missing source while exporting
8aa98e3
skip internal package export
5fa64f4
move some fatal to error and continue
e60dbb6
missing docstrings
c7409ab
run go fmt and plz fmt
be87020
move to error and continue for target lookup
6f73f78
rename new parser method on test files
762c016
use pkg.Metadata directly and remove intermediate pkg methods
406f95a
mutex in packagemetadata
b86ff9f
update stmt provider to avoid dereference
c7cd118
NewPackage with variadic optional functions
faf8c33
infof to debugf
dd8cfca
package metadata doc comments improvements
084f233
improve doc comments and adjust method visibility for export.go
bf0f734
hide build output when testing export
33d2bc2
open and write of exported package file merged into the same method
54f577c
update export_test.go with suggestions
ae5f520
apply review suggestions to export.go
5f0e549
rename and doc fields for scope
e59ab5b
revert new line change of target
917fe61
set builtin code filename for scope for debugging
b012ab8
Rework packagemetadata to return empty slices or nil instead of error…
2edfee0
linter fix imports
f59b5d0
ensure subrepo target exists. Failing to export //... on this repo
790a437
go test for filtered package
f589998
Add doc comments for providers in asp.interpreter
75521e2
test: function def in package file
2e2edde
unit testing current statement and active subincludes
0e74e53
remove nested maps and pointers in favor of using build labels
ef76bca
unexport noTrim implementation
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,183 @@ | ||
| package core | ||
|
|
||
| import ( | ||
| "slices" | ||
| "sync" | ||
| ) | ||
|
|
||
| // BuildStatement represents the start and end byte positions of a parsed statement in a BUILD file. | ||
| type BuildStatement struct { | ||
| Start, End int | ||
| } | ||
|
|
||
| // Len returns the byte length of the build statement. | ||
| func (bs *BuildStatement) Len() int64 { | ||
| return int64(bs.End - bs.Start) | ||
| } | ||
|
|
||
| // StartPos returns the starting byte position of the build statement. | ||
| func (bs *BuildStatement) StartPos() int64 { | ||
| return int64(bs.Start) | ||
| } | ||
|
|
||
| // BuildStatements is a slice of BuildStatement that implements sort.Interface. | ||
| type BuildStatements []BuildStatement | ||
|
|
||
| func (s BuildStatements) Len() int { return len(s) } | ||
| func (s BuildStatements) Swap(i, j int) { s[i], s[j] = s[j], s[i] } | ||
| func (s BuildStatements) Less(i, j int) bool { return s[i].StartPos() < s[j].StartPos() } | ||
|
|
||
| // BuildStatementProvider defines a closure that generates new build statements. | ||
| // It is used as an argument in PackageMetadata methods to defer evaluation, avoiding | ||
| // unnecessary computation when using the no-op implementation. | ||
| type BuildStatementProvider func() BuildStatement | ||
|
|
||
| // SubincludesLabelProvider defines a closure that generates labels for a subinclude statement. | ||
| // It is used as an argument in PackageMetadata methods to defer evaluation, avoiding | ||
| // unnecessary computation when using the no-op implementation. | ||
| type SubincludesLabelProvider func() BuildLabels | ||
|
|
||
| // PackageMetadata stores metadata about parsed BUILD files, mapping statements and subincludes | ||
| // to their respective targets. This supports additional logic for operations such as `plz export` | ||
| // but should be disabled for most operations by using the no-op implementation to avoid the overhead. | ||
| type PackageMetadata interface { | ||
| // RegisterStatementTarget records that the given build target was created as a result of the | ||
| // given statement being executed. This should only be called for statements in BUILD files. | ||
| RegisterStatementTarget(target *BuildTarget, stmtProvider BuildStatementProvider) | ||
| // RegisterRequiredSubinclude records that the given build target requires the given subinclude | ||
| // labels to be built. This is used to track which subinclude statements contributed to a target's | ||
| // definition. This should only be called for statements in BUILD files. | ||
| RegisterRequiredSubinclude(target *BuildTarget, labelProvider SubincludesLabelProvider) | ||
| // RegisterSubincludeStatement records that the given subinclude statement (provided by stmtProvider) | ||
| // includes the given build label. This should only be called for statements in BUILD files. | ||
| RegisterSubincludeStatement(label BuildLabel, stmtProvider BuildStatementProvider) | ||
| // FindStatement returns the build statement that was responsible for generating the given target. | ||
| // Returns nil if the target was not found in the recorded metadata. | ||
| FindStatement(target *BuildTarget) *BuildStatement | ||
| // FindTargets returns all build targets that were generated by the given build statement. | ||
| // Returns an empty slice if no targets were found for the given statement. | ||
| FindTargets(stmt *BuildStatement) []*BuildTarget | ||
| // FindRequiredSubincludes returns all subinclude labels that were required by the given target. | ||
| // The return value is empty if no subinclude information was found for the target. | ||
| FindRequiredSubincludes(target *BuildTarget) BuildLabels | ||
| // GetSubincludedLabels returns all build labels that were included by the given subinclude statement. | ||
| // Returns the labels or an empty slice if the statement wasn't found. | ||
| GetSubincludedLabels(stmt *BuildStatement) BuildLabels | ||
| } | ||
|
|
||
| // packageMetadataImpl is the default implementation of the PackageMetadata interface. | ||
| // It uses in-memory maps to track the relationships between BUILD file statements, | ||
| // subincludes, and the build targets they define. | ||
| type packageMetadataImpl struct { | ||
| // StmtToTarget maps each build statement (identified by its byte range in a BUILD file) | ||
| // to the targets it produced. Since a single statement (like a custom target or loop) | ||
| // can produce multiple targets, this is a one-to-many mapping. | ||
| StmtToTarget map[BuildStatement][]*BuildTarget | ||
| // TargetToSubinclude tracks the subinclude labels that were required for a target's | ||
| // definition. This allows mapping a target back to the subincluded labels required for building | ||
| // the target. | ||
| TargetToSubinclude map[*BuildTarget]BuildLabels | ||
| // LabelsPerSubincludeStmt maps a subinclude statement (identified by its position | ||
| // in the BUILD file) to the labels it explicitly subincludes. | ||
| LabelsPerSubincludeStmt map[BuildStatement]BuildLabels | ||
|
|
||
| // mutex protects concurrent access to the metadata maps during the parallel | ||
| // parsing of BUILD files. | ||
| mutex sync.RWMutex | ||
| } | ||
|
|
||
| func newPackageMetadata() PackageMetadata { | ||
| return &packageMetadataImpl{ | ||
| StmtToTarget: map[BuildStatement][]*BuildTarget{}, | ||
| TargetToSubinclude: map[*BuildTarget]BuildLabels{}, | ||
| LabelsPerSubincludeStmt: map[BuildStatement]BuildLabels{}, | ||
| } | ||
| } | ||
|
|
||
| func (m *packageMetadataImpl) RegisterStatementTarget(target *BuildTarget, stmtProvider BuildStatementProvider) { | ||
| stmt := stmtProvider() | ||
|
|
||
| m.mutex.Lock() | ||
| defer m.mutex.Unlock() | ||
| m.StmtToTarget[stmt] = append(m.StmtToTarget[stmt], target) | ||
| } | ||
|
|
||
| func (m *packageMetadataImpl) RegisterRequiredSubinclude(target *BuildTarget, labelProvider SubincludesLabelProvider) { | ||
| labels := labelProvider() | ||
|
|
||
| m.mutex.Lock() | ||
| defer m.mutex.Unlock() | ||
| m.TargetToSubinclude[target] = append(m.TargetToSubinclude[target], labels...) | ||
| } | ||
|
|
||
| func (m *packageMetadataImpl) RegisterSubincludeStatement(label BuildLabel, stmtProvider BuildStatementProvider) { | ||
| stmt := stmtProvider() | ||
|
|
||
| m.mutex.Lock() | ||
| defer m.mutex.Unlock() | ||
| m.LabelsPerSubincludeStmt[stmt] = append(m.LabelsPerSubincludeStmt[stmt], label) | ||
| } | ||
|
|
||
| func (m *packageMetadataImpl) FindStatement(target *BuildTarget) *BuildStatement { | ||
| m.mutex.RLock() | ||
| defer m.mutex.RUnlock() | ||
|
|
||
| for stmt, targets := range m.StmtToTarget { | ||
| if slices.Contains(targets, target) { | ||
| return &stmt | ||
| } | ||
| } | ||
| return nil | ||
| } | ||
|
|
||
| func (m *packageMetadataImpl) FindTargets(stmt *BuildStatement) []*BuildTarget { | ||
| m.mutex.RLock() | ||
| defer m.mutex.RUnlock() | ||
|
|
||
| return m.StmtToTarget[*stmt] | ||
| } | ||
|
|
||
| func (m *packageMetadataImpl) FindRequiredSubincludes(target *BuildTarget) BuildLabels { | ||
| m.mutex.RLock() | ||
| defer m.mutex.RUnlock() | ||
|
|
||
| return m.TargetToSubinclude[target] | ||
| } | ||
|
|
||
| func (m *packageMetadataImpl) GetSubincludedLabels(stmt *BuildStatement) BuildLabels { | ||
| m.mutex.RLock() | ||
| defer m.mutex.RUnlock() | ||
|
|
||
| return m.LabelsPerSubincludeStmt[*stmt] | ||
| } | ||
|
|
||
| // noopPackageMetadata implements the PackageMetadata interface with no-op methods. This is used to | ||
| // avoid the overhead of parsing metadata for operations that don't depend on it. | ||
| type noopPackageMetadata struct{} | ||
|
|
||
| func newNoopPackageMetadata() PackageMetadata { | ||
| return &noopPackageMetadata{} | ||
| } | ||
|
|
||
| func (n *noopPackageMetadata) RegisterStatementTarget(target *BuildTarget, stmtProvider BuildStatementProvider) { | ||
| } | ||
| func (n *noopPackageMetadata) RegisterRequiredSubinclude(target *BuildTarget, labelProvider SubincludesLabelProvider) { | ||
| } | ||
| func (n *noopPackageMetadata) RegisterSubincludeStatement(label BuildLabel, stmtProvider BuildStatementProvider) { | ||
| } | ||
| func (n *noopPackageMetadata) FindStatement(target *BuildTarget) *BuildStatement { | ||
| log.Fatalf("Metadata not tracked, using no-op implementation.") | ||
| return nil | ||
| } | ||
| func (n *noopPackageMetadata) FindTargets(stmt *BuildStatement) []*BuildTarget { | ||
| log.Fatalf("Metadata not tracked, using no-op implementation.") | ||
| return nil | ||
| } | ||
| func (n *noopPackageMetadata) FindRequiredSubincludes(target *BuildTarget) BuildLabels { | ||
| log.Fatalf("Metadata not tracked, using no-op implementation.") | ||
| return nil | ||
| } | ||
| func (n *noopPackageMetadata) GetSubincludedLabels(stmt *BuildStatement) BuildLabels { | ||
| log.Fatalf("Metadata not tracked, using no-op implementation.") | ||
| return nil | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.