Repository: goplus/llpkgstore
Pull request #30: fix: skip existed file for llcppg comparing test
Author: login: MeteorsLiu
Created: 2025-03-27T10:09:20Z | Merged: 2025-03-28T06:34:22Z

Fixes #29 

llcppg compare user-provided files with generated one, so it should not override any existed files for checking.
Besides, fix the `llpkgstore generate` because of `Installer` interface refactor in #21 

Upgrade to llcppg v0.2.0

Linked issue #29: unexpect verifacation fail
llpkg.pkg
```
{
  "upstream": {
    "package": {
      "name": "libxml2",
      "version": "2.11.6"
    },
    "installer":{
      "name": "conan",
      "config" : {
        "options": "iconv=False"
      }
    }
  }
}
```
llcppg.cfg
```
{
	"name": "libxml2",
	"cflags": "$(pkg-config --cflags libxml-2.0)",
	"libs": "$(pkg-config --libs libxml-2.0)",
	"include": [
		"libxml/parserInternals.h",
		"libxml/xmlschemastypes.h",
		"libxml/xmlreader.h",
		"libxml/HTMLtree.h",
		"libxml/xpointer.h",
		"libxml/xpathInternals.h",
		"libxml/c14n.h",
		"libxml/debugXML.h",
		"libxml/threads.h",
		"libxml/xlink.h",
		"libxml/entities.h",
		"libxml/globals.h",
		"libxml/hash.h",
		"libxml/SAX.h",
		"libxml/SAX2.h",
		"libxml/xpath.h",
		"libxml/parser.h",
		"libxml/xmlwriter.h",
		"libxml/pattern.h",
		"libxml/relaxng.h",
		"libxml/schemasInternals.h",
		"libxml/schematron.h",
		"libxml/HTMLparser.h",
		"libxml/tree.h",
		"libxml/uri.h",
		"libxml/valid.h",
		"libxml/xinclude.h",
		"libxml/encoding.h",
		"libxml/xmlIO.h",
		"libxml/catalog.h",
		"libxml/xmlerror.h",
		"libxml/xmlschemas.h",
		"libxml/xmlmemory.h",
		"libxml/xmlsave.h",
		"libxml/xmlregexp.h",
		"libxml/chvalid.h",
		"libxml/xmlautomata.h",
		"libxml/xmlmodule.h",
		"libxml/xmlstring.h",
		"libxml/xmlunicode.h",
		"libxml/dict.h",
		"libxml/nanohttp.h",
		"libxml/nanoftp.h",
		"libxml/list.h",
		"libxml/xmlversion.h",
		"libxml/xmlexports.h",
		"win32config.h"
	],
	"deps":["c","c/os"],
	"trimPrefixes": ["xml","XML_","XML"],
	"cplusplus": false
}
```

---

https://github.com/luoliwoshang/goplus-llpkg/actions/runs/14102117265/job/39501231786?pr=10
```
2025/03/27 08:48:53 llcppg: check fail: 
unexpected file: valid.go
Error: Process completed with exit code 1.
```

https://github.com/MeteorsLiu/llpkg/actions/runs/14102743141/job/39502347425
 https://github.com/MeteorsLiu/llpkg/actions/runs/14102743141/artifacts/2829911505

Some artifacts are missing from the Linux llcppg output


![Image](https://github.com/user-attachments/assets/7d1a55eb-1de7-47b7-ba43-902524a12f47)
Linked issue comments: user: login: MeteorsLiu
created_at: 2025-03-28T01:20:24Z
body: This is caused by `CopyFS` function in Go1.23, they don't handle existed file and return an error.
In that case, Copy process will be interrupted because we always copy `llcppg.pub` for reproducible generation.
author_association: CONTRIBUTOR
user: login: luoliwoshang
created_at: 2025-03-28T07:44:22Z
body: with the latest  https://github.com/goplus/llpkgstore/pull/30 update,this verifiy can pass corrrectly

https://github.com/luoliwoshang/goplus-llpkg/pull/12
https://github.com/luoliwoshang/goplus-llpkg/actions/runs/14124193136/job/39569691217?pr=12
author_association: MEMBER

Diff:
diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml
index cad2970..f3215f0 100644
--- a/.github/workflows/test.yaml
+++ b/.github/workflows/test.yaml
@@ -14,6 +14,7 @@ jobs:
         go:
           - 1.22.x
           - 1.23.x
+        llcppg: [v0.2.0]
     steps:
       - name: Check out code
         uses: actions/checkout@v4
@@ -27,7 +28,7 @@ jobs:
         with:
           repository: 'goplus/llcppg'
           path: .llcppg
-          ref: 'v0.1.0'
+          ref: ${{matrix.llcppg}}
       - name: Set up Go
         uses: actions/setup-go@v5
         with:
@@ -54,9 +55,9 @@ jobs:
         run: |
           llgo install ./_xtool/llcppsymg
           llgo install ./_xtool/llcppsigfetch
-          go install github.com/goplus/llcppg/cmd/llcppcfg@v0.1.0
-          go install github.com/goplus/llcppg/cmd/gogensig@v0.1.0
-          go install github.com/goplus/llcppg@v0.1.0
+          go install github.com/goplus/llcppg/cmd/llcppcfg@${{matrix.llcppg}}
+          go install github.com/goplus/llcppg/cmd/gogensig@${{matrix.llcppg}}
+          go install github.com/goplus/llcppg@${{matrix.llcppg}}
       - name: Check Conan environment
         run: conan profile detect
       - name: Download Go modules
diff --git a/cmd/llpkgstore/internal/generate.go b/cmd/llpkgstore/internal/generate.go
index f15f8b9..49da757 100644
--- a/cmd/llpkgstore/internal/generate.go
+++ b/cmd/llpkgstore/internal/generate.go
@@ -9,6 +9,7 @@ import (
 	"github.com/goplus/llpkgstore/config"
 	"github.com/goplus/llpkgstore/internal/actions/file"
 	"github.com/goplus/llpkgstore/internal/actions/generator/llcppg"
+	"github.com/goplus/llpkgstore/internal/actions/pc"
 	"github.com/spf13/cobra"
 )
 
@@ -37,29 +38,34 @@ func runLLCppgGenerateWithDir(dir string) {
 		log.Fatal(err)
 	}
 	log.Printf("Start to generate %s", uc.Pkg.Name)
-	_, err = uc.Installer.Install(uc.Pkg, dir)
+
+	tempDir, err := os.MkdirTemp("", "llpkg-tool")
+	if err != nil {
+		log.Fatal(err)
+	}
+	defer os.RemoveAll(tempDir)
+	pcName, err := uc.Installer.Install(uc.Pkg, tempDir)
 	if err != nil {
 		log.Fatal(err)
 	}
+	// copy file for debugging.
+	file.CopyFilePattern(tempDir, dir, "*.pc")
 	// try llcppcfg if llcppg.cfg dones't exist
 	if _, err := os.Stat(filepath.Join(dir, "llcppg.cfg")); os.IsNotExist(err) {
-		cmd := exec.Command("llcppcfg", uc.Pkg.Name)
+		cmd := exec.Command("llcppcfg", pcName)
 		cmd.Dir = dir
-
+		pc.SetPath(cmd, tempDir)
 		ret, err := cmd.CombinedOutput()
 		if err != nil {
 			log.Fatalf("llcppcfg execute fail: %s", string(ret))
 		}
 	}
 
-	generator := llcppg.New(dir, cfg.Upstream.Package.Name)
+	generator := llcppg.New(dir, cfg.Upstream.Package.Name, tempDir)
 
 	if err := generator.Generate(dir); err != nil {
 		log.Fatal(err)
 	}
-
-	file.RemovePattern("*.sh")
-	file.RemovePattern("*.bat")
 }
 
 func runLLCppgGenerate(_ *cobra.Command, args []string) {
diff --git a/cmd/llpkgstore/internal/verification.go b/cmd/llpkgstore/internal/verification.go
index 777ef83..10b86c3 100644
--- a/cmd/llpkgstore/internal/verification.go
+++ b/cmd/llpkgstore/internal/verification.go
@@ -35,10 +35,11 @@ func runLLCppgVerificationWithDir(dir string) {
 	if err != nil {
 		log.Fatal(err)
 	}
-	generator := llcppg.New(dir, cfg.Upstream.Package.Name)
+	generator := llcppg.New(dir, cfg.Upstream.Package.Name, dir)
 
 	generated := filepath.Join(dir, ".generated")
 	os.Mkdir(generated, 0777)
+	// TODO(ghl): upload generated result to artifact for debugging.
 	defer os.Remove(generated)
 
 	if err := generator.Generate(generated); err != nil {
diff --git a/internal/actions/file/file.go b/internal/actions/file/file.go
index b8372b4..9bdb7a7 100644
--- a/internal/actions/file/file.go
+++ b/internal/actions/file/file.go
@@ -26,7 +26,7 @@ import (
 // Symbolic links in dir are followed.
 //
 // Copying stops at and returns the first error encountered.
-func CopyFS(dir string, fsys fs.FS) error {
+func CopyFS(dir string, fsys fs.FS, skipExist bool) error {
 	return fs.WalkDir(fsys, ".", func(path string, d fs.DirEntry, err error) error {
 		if err != nil {
 			return err
@@ -53,8 +53,15 @@ func CopyFS(dir string, fsys fs.FS) error {
 		if err != nil {
 			return err
 		}
-		w, err := os.OpenFile(newPath, os.O_TRUNC|os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0666|info.Mode()&0777)
+		mode := os.O_TRUNC | os.O_CREATE | os.O_WRONLY
+		if skipExist {
+			mode = os.O_CREATE | os.O_EXCL | os.O_WRONLY
+		}
+		w, err := os.OpenFile(newPath, mode, 0666|info.Mode()&0777)
 		if err != nil {
+			if skipExist {
+				return nil
+			}
 			return err
 		}
 
diff --git a/internal/actions/file/file_test.go b/internal/actions/file/file_test.go
index 5f18e7b..5add302 100644
--- a/internal/actions/file/file_test.go
+++ b/internal/actions/file/file_test.go
@@ -4,6 +4,7 @@ import (
 	"archive/zip"
 	"io"
 	"os"
+	"path/filepath"
 	"testing"
 )
 
@@ -98,3 +99,44 @@ func TestCopyPattern(t *testing.T) {
 		}
 	}
 }
+
+func TestCopySkip(t *testing.T) {
+	from, _ := os.MkdirTemp("", "testcopy-from")
+	defer os.RemoveAll(from)
+
+	to, _ := os.MkdirTemp("", "testcopy-to")
+	defer os.RemoveAll(to)
+
+	os.WriteFile(filepath.Join(from, "aaa.test"), []byte("123"), 0644)
+	os.WriteFile(filepath.Join(to, "aaa.test"), []byte("456"), 0644)
+
+	err := CopyFS(to, os.DirFS(from), true)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	toContent, err := os.ReadFile(filepath.Join(to, "aaa.test"))
+	if err != nil {
+		t.Error(err)
+		return
+	}
+
+	if string(toContent) != "456" {
+		t.Errorf("unexpected skip file: want: 456 got: %s", string(toContent))
+	}
+
+	err = CopyFS(to, os.DirFS(from), false)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	toContent, err = os.ReadFile(filepath.Join(to, "aaa.test"))
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	if string(toContent) != "123" {
+		t.Errorf("unexpected skip file: want: 123 got: %s", string(toContent))
+	}
+}
diff --git a/internal/actions/generator/llcppg/llcppg.go b/internal/actions/generator/llcppg/llcppg.go
index 752fce3..349afeb 100644
--- a/internal/actions/generator/llcppg/llcppg.go
+++ b/internal/actions/generator/llcppg/llcppg.go
@@ -66,11 +66,12 @@ func isExitedUnexpectedly(err error) bool {
 // llcppgGenerator implements Generator interface, which use llcppg tool to generate llpkg.
 type llcppgGenerator struct {
 	dir         string // llcppg.cfg abs path
+	pcDir       string
 	packageName string
 }
 
-func New(dir, packageName string) generator.Generator {
-	return &llcppgGenerator{dir: dir, packageName: packageName}
+func New(dir, packageName, pcDir string) generator.Generator {
+	return &llcppgGenerator{dir: dir, packageName: packageName, pcDir: pcDir}
 }
 
 // normalizeModulePath returns a normalized module path like
@@ -121,11 +122,11 @@ func (l *llcppgGenerator) Generate(toDir string) error {
 	if err := l.copyConfigFileTo(path); err != nil {
 		return errors.Join(ErrLlcppgGenerate, err)
 	}
-	cmd := exec.Command("llcppg", llcppgConfigFile)
+	cmd := exec.Command("llcppg", "-mod", l.normalizeModulePath(), llcppgConfigFile)
 	cmd.Dir = path
 	cmd.Stdout = os.Stdout
 	cmd.Stderr = os.Stderr
-	lockGoVersion(cmd, l.dir)
+	lockGoVersion(cmd, l.pcDir)
 
 	// llcppg may exit with an error, which may be caused by Stderr.
 	// To avoid that case, we have to check its exit code.
@@ -137,15 +138,13 @@ func (l *llcppgGenerator) Generate(toDir string) error {
 	if _, err := os.Stat(generatedPath); os.IsNotExist(err) {
 		return errors.Join(ErrLlcppgCheck, errors.New("generate fail"))
 	}
-	// edit go.mod
-	cmd = exec.Command("go", "mod", "edit", "-module", l.normalizeModulePath())
-	cmd.Dir = generatedPath
-	lockGoVersion(cmd, l.dir)
-
-	cmd.Run()
-
 	// copy out the generated result
-	file.CopyFS(path, os.DirFS(generatedPath))
+	// be careful: llcppg result MUST not override existed file,
+	// otherwise, checking is meaningless.
+	err = file.CopyFS(path, os.DirFS(generatedPath), true)
+	if err != nil {
+		return errors.Join(ErrLlcppgGenerate, err)
+	}
 
 	os.RemoveAll(generatedPath)
 	return nil
diff --git a/internal/actions/generator/llcppg/llcppg_test.go b/internal/actions/generator/llcppg/llcppg_test.go
index 94518f5..a50fdd8 100644
--- a/internal/actions/generator/llcppg/llcppg_test.go
+++ b/internal/actions/generator/llcppg/llcppg_test.go
@@ -42,6 +42,10 @@ func checkGoMod(t *testing.T, file string) {
 	if f.Go.Version != "1.20" {
 		t.Errorf("unexpected version: got: %s", f.Go.Version)
 	}
+	if f.Module.Mod.Path != goplusRepo+"cjson" {
+		t.Errorf("unexpected module path: got: %s", f.Module.Mod.Path)
+
+	}
 }
 
 func TestHash(t *testing.T) {
@@ -86,7 +90,7 @@ func TestLlcppg(t *testing.T) {
 	os.Mkdir("testgenerate", 0777)
 	defer os.RemoveAll("testgenerate")
 	path, _ := filepath.Abs("testgenerate")
-	generator := New(path, "cjson")
+	generator := New(path, "cjson", path)
 
 	os.WriteFile("testgenerate/llcppg.cfg", []byte(testLlcppgConfig), 0755)
 	os.WriteFile("testgenerate/llpkg.cfg", []byte(testLLPkgConfig), 0755)
diff --git a/upstream/installer/conan/conaninst.go b/upstream/installer/conan/conaninst.go
index 058e2c6..b784f7d 100644
--- a/upstream/installer/conan/conaninst.go
+++ b/upstream/installer/conan/conaninst.go
@@ -163,7 +163,7 @@ func (c *conanInstaller) Install(pkg upstream.Package, outputDir string) (string
 		return "", err
 	}
 
-	err = file.CopyFS(outputDir, os.DirFS(binaryDir))
+	err = file.CopyFS(outputDir, os.DirFS(binaryDir), false)
 	if err != nil {
 		return "", err
 	}


Reviews:
user: login: aofei
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-28T06:11:37Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR fixes issue #29 by ensuring that generated files from llcppg do not overwrite user-provided files during testing and adjusts the llpkgstore generate command to accommodate the updated Installer interface. Key changes include modifying the file copying behavior to skip existing files, updating generator constructors with an additional directory parameter, and aligning version references to llcppg v0.2.0 in both code and CI configuration.

### Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

<details>
<summary>Show a summary per file</summary>

| File                                                              | Description                                                        |
|-------------------------------------------------------------------|--------------------------------------------------------------------|
| upstream/installer/conan/conaninst.go                             | Updates file.CopyFS call with an additional parameter              |
| internal/actions/generator/llcppg/llcppg_test.go                    | Adjusts test expectations and generator instantiation with new param |
| internal/actions/generator/llcppg/llcppg.go                         | Updates New signature, command flag, and parameter usage             |
| internal/actions/file/file.go                                      | Modifies CopyFS to accept a skip-existence flag for file copying       |
| cmd/llpkgstore/internal/verification.go, generate.go               | Propagates changes to generator invocations                           |
| .github/workflows/test.yaml                                         | Upgrades llcppg version to v0.2.0 in CI commands                        |
</details>



<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**internal/actions/file/file.go:57**
* [nitpick] Consider renaming the parameter 'skipExist' to 'skipExisting' to improve clarity.
```
if skipExist {
```
**internal/actions/file/file.go:62**
* When skipExist is true, the function returns nil for any error from os.OpenFile, which may suppress errors unrelated to file existence. Consider checking that the error is due to the file's existence before silently bypassing it.
```
if err != nil {
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T06:12:14Z
user: login: MeteorsLiu
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T06:27:27Z
user: login: MeteorsLiu
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-28T06:27:39Z
user: login: aofei
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-28T06:34:16Z

Review comments:
diff_hunk: @@ -14,6 +14,7 @@ jobs:
         go:
           - 1.22.x
           - 1.23.x
+        llcppg-version: [v0.2.0]
path: .github/workflows/test.yaml
user: login: aofei
body: 建议统一下名称风格，这里叫 `llcppg` 应该更合适些
created_at: 2025-03-28T06:09:07Z
author_association: MEMBER
diff_hunk: @@ -37,29 +38,34 @@ func runLLCppgGenerateWithDir(dir string) {
 		log.Fatal(err)
 	}
 	log.Printf("Start to generate %s", uc.Pkg.Name)
-	_, err = uc.Installer.Install(uc.Pkg, dir)
+
+	temp, err := os.MkdirTemp("", "llpkg-tool")
path: cmd/llpkgstore/internal/generate.go
user: login: aofei
body: 对于临时目录通常建议叫 `tempDir`，好处是从名称上可以知道它是一个目录路径，而非普通文件路径，避免用错
created_at: 2025-03-28T06:10:27Z
author_association: MEMBER
diff_hunk: @@ -14,6 +14,7 @@ jobs:
         go:
           - 1.22.x
           - 1.23.x
+        llcppg-version: [v0.2.0]
path: .github/workflows/test.yaml
user: login: MeteorsLiu
body: Done in [chore: adjust workflow field](https://github.com/goplus/llpkgstore/pull/30/commits/3e17926670d146a9672135f6100c2f7dd26fe064)
created_at: 2025-03-28T06:27:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -37,29 +38,34 @@ func runLLCppgGenerateWithDir(dir string) {
 		log.Fatal(err)
 	}
 	log.Printf("Start to generate %s", uc.Pkg.Name)
-	_, err = uc.Installer.Install(uc.Pkg, dir)
+
+	temp, err := os.MkdirTemp("", "llpkg-tool")
path: cmd/llpkgstore/internal/generate.go
user: login: MeteorsLiu
body: Done in [chore: adjust var name](https://github.com/goplus/llpkgstore/pull/30/commits/1e29be006206745e160b8a79b0bd012e50dc8a71)
created_at: 2025-03-28T06:27:39Z
author_association: CONTRIBUTOR

PR comments:
user: login: codecov[bot]
created_at: 2025-03-27T10:12:04Z
body: ## [Codecov](https://app.codecov.io/gh/goplus/llpkgstore/pull/30?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goplus) Report
Attention: Patch coverage is `48.38710%` with `16 lines` in your changes missing coverage. Please review.
> Project coverage is 38.43%. Comparing base [(`930c6a1`)](https://app.codecov.io/gh/goplus/llpkgstore/commit/930c6a1006c41201bd08e0e9ad6b2024f6803fd6?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goplus) to head [(`1e29be0`)](https://app.codecov.io/gh/goplus/llpkgstore/commit/1e29be006206745e160b8a79b0bd012e50dc8a71?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goplus).
> Report is 1 commits behind head on main.

| [Files with missing lines](https://app.codecov.io/gh/goplus/llpkgstore/pull/30?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goplus) | Patch % | Lines |
|---|---|---|
| [cmd/llpkgstore/internal/generate.go](https://app.codecov.io/gh/goplus/llpkgstore/pull/30?src=pr&el=tree&filepath=cmd%2Fllpkgstore%2Finternal%2Fgenerate.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goplus#diff-Y21kL2xscGtnc3RvcmUvaW50ZXJuYWwvZ2VuZXJhdGUuZ28=) | 0.00% | [11 Missing :warning: ](https://app.codecov.io/gh/goplus/llpkgstore/pull/30?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goplus) |
| [internal/actions/generator/llcppg/llcppg.go](https://app.codecov.io/gh/goplus/llpkgstore/pull/30?src=pr&el=tree&filepath=internal%2Factions%2Fgenerator%2Fllcppg%2Fllcppg.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goplus#diff-aW50ZXJuYWwvYWN0aW9ucy9nZW5lcmF0b3IvbGxjcHBnL2xsY3BwZy5nbw==) | 62.50% | [2 Missing and 1 partial :warning: ](https://app.codecov.io/gh/goplus/llpkgstore/pull/30?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goplus) |
| [cmd/llpkgstore/internal/verification.go](https://app.codecov.io/gh/goplus/llpkgstore/pull/30?src=pr&el=tree&filepath=cmd%2Fllpkgstore%2Finternal%2Fverification.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goplus#diff-Y21kL2xscGtnc3RvcmUvaW50ZXJuYWwvdmVyaWZpY2F0aW9uLmdv) | 0.00% | [2 Missing :warning: ](https://app.codecov.io/gh/goplus/llpkgstore/pull/30?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goplus) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main      #30      +/-   ##
==========================================
+ Coverage   37.96%   38.43%   +0.47%     
==========================================
  Files          33       33              
  Lines        1657     1665       +8     
==========================================
+ Hits          629      640      +11     
+ Misses        950      942       -8     
- Partials       78       83       +5     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/goplus/llpkgstore/pull/30?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goplus).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=goplus).

<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE
user: login: qiniu-x[bot]
created_at: 2025-03-28T02:57:59Z
body: **[Git-flow]** Hi @MeteorsLiu, There are some suggestions for your information:

---


> 
### Rebase suggestions
* Following commits seems generated via `git merge` 
 
  > Merge branch 'main' of https://github.com/goplus/llpkgstore into fix-llcppg-compare

 Which seems insignificant, recommend to use **`git rebase`** command to reorganize your PR. 



For other `git-flow` instructions, recommend refer to [these examples](https://github.com/qiniu/reviewbot/blob/master/docs/engineering-practice/git-flow-instructions_zh.md).


<details>

If you have any questions about this comment, feel free to raise an issue here:

- **https://github.com/qiniu/reviewbot**

</details>

author_association: CONTRIBUTOR
user: login: MeteorsLiu
created_at: 2025-03-28T03:13:24Z
body: need review @aofei 
author_association: CONTRIBUTOR