Skip to content

feat(internal/postprocessing): add replace and replaceRegex functions#6412

Open
yangyzs wants to merge 3 commits into
googleapis:mainfrom
yangyzs:feat/replace
Open

feat(internal/postprocessing): add replace and replaceRegex functions#6412
yangyzs wants to merge 3 commits into
googleapis:mainfrom
yangyzs:feat/replace

Conversation

@yangyzs

@yangyzs yangyzs commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Add the replace and replaceRegex functions to the postprocessing package. They perform exact string and regex replacements in files and return an error if the target text is not found.

Fixes #6297

Add the replace and replaceRegex functions to the postprocessing package. They perform exact string and regex replacements in files and return an error if the target text is not found.

Fixes googleapis#6297
@yangyzs yangyzs requested a review from a team as a code owner June 12, 2026 16:34

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

Copy link
Copy Markdown
Contributor

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 introduces two new utility functions, Replace and ReplaceRegex, to the postprocessing package for finding and replacing text in files, along with comprehensive unit tests. The review feedback suggests optimizing both functions by performing search and replacement operations directly on []byte slices using the bytes package and regexp.Regexp.ReplaceAll instead of converting the file contents to strings, which avoids unnecessary allocations and copies.

Comment on lines 18 to 26
import (
"errors"
"fmt"
"os"
"regexp"
"strings"

"github.com/googleapis/librarian/internal/filesystem"
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

To support efficient byte-level operations without converting file contents to strings, we should import the bytes package.

Suggested change
import (
"errors"
"fmt"
"os"
"regexp"
"strings"
"github.com/googleapis/librarian/internal/filesystem"
)
import (
"bytes"
"errors"
"fmt"
"os"
"regexp"
"strings"
"github.com/googleapis/librarian/internal/filesystem"
)

Comment thread internal/postprocessing/fileops.go
Comment thread internal/postprocessing/fileops.go
Comment thread internal/postprocessing/fileops_test.go Outdated
t.Fatal(err)
}
err := Replace(path, "Apple", "Go")
if !errors.Is(err, ErrTextNotFound) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I went with errors.Is and a sentinel error here to align with the error testing guidelines. Let me know if you'd prefer the simpler strings.Contains approach instead.

Address review feedback to use []byte operations instead of string conversions to avoid unnecessary memory allocations.
// It returns an error if the target file does not exist or if the pattern matches no text.
func ReplaceRegex(path, pattern, replacement string) error {
if !strings.HasPrefix(pattern, "(?") {
pattern = "(?m)" + pattern

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why do we need this step?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

s.replace(...) in synthtool uses re.MULTILINE by default (link). It makes file replacements search line-by-line.

In Go, (?m) ensures it works the exact same way, allowing ine-by-line regex in librarian.yaml. Otherwise ^ only matches the very beginning of the whole file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Got it, could you add a comment in the code?

Comment thread internal/postprocessing/fileops.go Outdated
Comment thread internal/postprocessing/fileops.go Outdated
Comment thread internal/postprocessing/fileops.go Outdated
Comment thread internal/postprocessing/fileops_test.go Outdated
Comment thread internal/postprocessing/fileops_test.go Outdated
Comment thread internal/postprocessing/fileops_test.go Outdated
Comment thread internal/postprocessing/fileops_test.go Outdated
original := "World"
replacement := "Go"
want := "Hello Go"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: remove this empty line.

}
}

func TestReplaceRegex(t *testing.T) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

java: create replace and replaceRegex functions in postprocessing package

2 participants