Skip to content

Conversation

@soorya38
Copy link

@soorya38 soorya38 commented Jan 19, 2026

This PR significantly enhances the copy (and copy_no_overwrite) command in buildozer by adding support for cross-file operations.

Previously, buildozer assumed that the source rule for a copy operation existed in the same BUILD file as the target rule. This change removes that limitation.

Related issue: #1436


What’s Changed

When the source rule label refers to a different package/file (for example):

buildozer 'copy deps //pkg1:rule1' //pkg2:rule2

buildozer will now:

  1. Detect that the source rule is located in a different BUILD file
  2. Load and parse the source BUILD file on demand
  3. Retrieve the requested attribute from the source rule
  4. Apply it to the target rule in the current file

This enables copying or moving attributes across multiple BUILD files, addressing a known limitation in current behavior.


Testing

  • Local Reproduction
    Verified using a script that creates two packages (pkg1, pkg2) and successfully copies the deps attribute from a rule in pkg1 to a rule in pkg2.

  • Existing Tests
    Ran the following to ensure no regressions:

    go test ./edit/...

Related Issue


Checklist

  • Signed the CLA (Contributor License Agreement)
  • Ran tests (go test ./...)

Modify copyAttributeBetweenRules to handle cross-package labels.
When a label refers to a rule in a different file, the source file is loaded and parsed on-demand to retrieve the attribute.
This enables copy and copy_no_overwrite commands to work across files.
@soorya38 soorya38 requested a review from a team as a code owner January 19, 2026 11:40
@soorya38 soorya38 requested review from vladmos and removed request for a team January 19, 2026 11:40
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @soorya38, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly extends the capabilities of buildozer's copy functionality by enabling attribute transfers between rules located in different BUILD files. This enhancement addresses a long-standing limitation, allowing for more flexible and powerful build file manipulations across a project's package structure, improving the tool's utility for managing complex build configurations.

Highlights

  • Cross-File Copy Operations: Enhanced buildozer's copy and copy_no_overwrite commands to support attribute copying between rules located in different BUILD files.
  • Removed Same-File Limitation: Eliminated the previous restriction that required source rules for copy operations to reside in the same BUILD file as the target rule.
  • Dynamic BUILD File Loading: Implemented logic to dynamically detect, load, and parse external BUILD files when a source rule label refers to a different package, allowing attributes to be retrieved and applied across files.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a great enhancement, adding support for cross-file copy operations in buildozer. The overall approach is solid. I've found a couple of high-severity bugs related to workspace root detection and rule lookups for same-file absolute labels that should be addressed. I've also included a suggestion to improve performance by caching parsed files to avoid redundant I/O. With these changes, the new functionality will be more robust and efficient.

func copyAttributeBetweenRules(env CmdEnvironment, attrName string, from string) (*build.File, error) {
fromRule := FindRuleByName(env.File, from)
// Check if the source rule is in another package
buildFile, _, _, rule := InterpretLabelForWorkspaceLocation(NewOpts().RootDir, from)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The call to InterpretLabelForWorkspaceLocation uses NewOpts().RootDir, which creates a new Options object with a default (empty) RootDir. This ignores the RootDir that might have been passed to buildozer via command-line flags, which can lead to incorrect workspace root detection.

To fix this, copyAttributeBetweenRules should accept the *Options struct (passed down from cmdCopy/cmdCopyNoOverwrite) and use opts.RootDir here.

Suggested change
buildFile, _, _, rule := InterpretLabelForWorkspaceLocation(NewOpts().RootDir, from)
buildFile, _, _, rule := InterpretLabelForWorkspaceLocation(opts.RootDir, from)

fromRule = FindRuleByName(f, rule)
} else {
// The rule is in the same file
fromRule = FindRuleByName(env.File, from)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

When the source rule is in the same file, you are calling FindRuleByName with from, which is the full label string (e.g., //pkg:rule). However, FindRuleByName likely expects just the rule name part. This is inconsistent with the if branch which correctly uses the parsed rule name.

This will cause lookups to fail for rules specified with an absolute label that are in the current file. You should use the rule variable here for correctness and consistency.

Suggested change
fromRule = FindRuleByName(env.File, from)
fromRule = FindRuleByName(env.File, rule)

Comment on lines +818 to +828
if buildFile != "" && buildFile != env.File.Path {
// The rule is in another file, we need to load it
data, _, err := file.ReadFile(buildFile)
if err != nil {
return nil, fmt.Errorf("could not read file '%s': %v", buildFile, err)
}
f, err := build.Parse(buildFile, data)
if err != nil {
return nil, fmt.Errorf("could not parse file '%s': %v", buildFile, err)
}
fromRule = FindRuleByName(f, rule)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This implementation reads and parses the source BUILD file every time a copy command for a rule in that file is executed. If multiple copy commands in a single buildozer invocation reference rules from the same external file, that file will be read and parsed multiple times, which is inefficient.

For example: buildozer "copy attr1 //pkg1:rule1" //pkg2:ruleA "copy attr2 //pkg1:rule1" //pkg2:ruleB would parse pkg1's BUILD file twice.

Consider introducing a cache for parsed *build.File objects that lives for the duration of the buildozer run. This would improve performance for commands that operate on multiple rules from the same external package. The cache could be keyed by file path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Buildozer stack-overflows on Windows platforms, when not in WORKSPACE directory

1 participant