This is an automated email from the ASF dual-hosted git repository.

kezhenxu94 pushed a commit to branch feature/save-licenses
in repository https://gitbox.apache.org/repos/asf/skywalking-eyes.git

commit 47f0270f06d4ad85b24556cb0d985ea9257075d9
Author: kezhenxu94 <[email protected]>
AuthorDate: Fri Sep 10 23:54:02 2021 +0800

    feature: support saving dependencies' licenses
---
 README.md                | 72 ++++++++++++++++++++++++++++++++----------------
 commands/deps_resolve.go | 43 +++++++++++++++++++++++++++++
 2 files changed, 92 insertions(+), 23 deletions(-)

diff --git a/README.md b/README.md
index f87130a..61f0bbd 100644
--- a/README.md
+++ b/README.md
@@ -19,14 +19,15 @@ To use License-Eye in GitHub Actions, add a step in your 
GitHub workflow.
   uses: apache/skywalking-eyes@main      # always prefer to use a revision 
instead of `main`.
   env:
     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}  # needed only when you want 
License-Eye to comment on the pull request.
-  # with:
+      # with:
       # Optional: set the log level. The default value is `info`.
       # log: debug
       # Optional: set the config file. The default value is `.licenserc.yaml`.
-      # config: .licenserc.yaml
+    # config: .licenserc.yaml
 ```
 
-Add a `.licenserc.yaml` in the root of your project, for Apache Software 
Foundation projects, the following configuration should be enough.
+Add a `.licenserc.yaml` in the root of your project, for Apache Software 
Foundation projects, the following
+configuration should be enough.
 
 ```yaml
 header:
@@ -112,8 +113,11 @@ INFO Totally checked 20 files, valid: 10, invalid: 10, 
ignored: 0, fixed: 10
 
 This command serves as assistance for human beings to audit the dependencies 
license, it's exit code is always 0.
 
+You can also use the `--output` or `-o` to save the dependencies' `LICENSE` 
files to a specified directory so that you
+can put them in distribution package if needed.
+
 ```bash
-bin/darwin/license-eye -c test/testdata/.licenserc_for_test_check.yaml dep 
resolve
+bin/darwin/license-eye -c test/testdata/.licenserc_for_test_check.yaml dep 
resolve -o ./dependencies/licenses
 INFO GITHUB_TOKEN is not set, license-eye won't comment on the pull request
 INFO Loading configuration from file: 
test/testdata/.licenserc_for_test_check.yaml
 WARNING Failed to resolve the license of dependency: gopkg.in/yaml.v3 cannot 
identify license content
@@ -245,21 +249,36 @@ dependency: # <9>
 ```
 
 1. The `header` section is configurations for source codes license header.
-2. The [SPDX ID](https://spdx.org/licenses/) of the license, it’s convenient 
when your license is standard SPDX license, so that you can simply specify this 
identifier without copying the whole license `content` or `pattern`. This will 
be used as the content when `fix` command needs to insert a license header.
+2. The [SPDX ID](https://spdx.org/licenses/) of the license, it’s convenient 
when your license is standard SPDX license,
+   so that you can simply specify this identifier without copying the whole 
license `content` or `pattern`. This will be
+   used as the content when `fix` command needs to insert a license header.
 3. The copyright owner to replace the `[owner]` in the `SPDX-ID` license 
template.
-4. If you are not using the standard license text, you can paste your license 
text here, this will be used as the content when `fix` command needs to insert 
a license header, if both `license` and `SPDX-ID` are specified, `license` wins.
-5. The `pattern` is an optional regexp. You don’t need this if all the file 
headers are the same as `license` or the license of `SPDX-ID`, otherwise you 
need to compose a pattern that matches your license texts.
-6. The `paths` are the path list that will be checked (and fixed) by 
license-eye, default is `['**']`. Formats like `**/*`.md and `**/bin/**` are 
supported.
-7. The `paths-ignore` are the path list that will be ignored by license-eye. 
By default, `.git` and the content in `.gitignore` will be inflated into the 
`paths-ignore` list.
-8. On what condition License-Eye will comment the check results on the pull 
request, `on-failure`, `always` or `never`. Options other than `never` require 
the environment variable `GITHUB_TOKEN` to be set.
+4. If you are not using the standard license text, you can paste your license 
text here, this will be used as the
+   content when `fix` command needs to insert a license header, if both 
`license` and `SPDX-ID` are specified, `license`
+   wins.
+5. The `pattern` is an optional regexp. You don’t need this if all the file 
headers are the same as `license` or the
+   license of `SPDX-ID`, otherwise you need to compose a pattern that matches 
your license texts.
+6. The `paths` are the path list that will be checked (and fixed) by 
license-eye, default is `['**']`. Formats
+   like `**/*`.md and `**/bin/**` are supported.
+7. The `paths-ignore` are the path list that will be ignored by license-eye. 
By default, `.git` and the content
+   in `.gitignore` will be inflated into the `paths-ignore` list.
+8. On what condition License-Eye will comment the check results on the pull 
request, `on-failure`, `always` or `never`.
+   Options other than `never` require the environment variable `GITHUB_TOKEN` 
to be set.
 9. `dependency` section is configurations for resolving dependencies' licenses.
-10. `files` are the files that declare the dependencies of a project, 
typically, `go.mo` in Go project, `pom.xml` in maven project, and 
`package.json` in NodeJS project. If it's a relative path, it's relative to the 
`.licenserc.yaml`.
+10. `files` are the files that declare the dependencies of a project, 
typically, `go.mo` in Go project, `pom.xml` in
+    maven project, and `package.json` in NodeJS project. If it's a relative 
path, it's relative to the `.licenserc.yaml`
+    .
 
-**NOTE**: When the `SPDX-ID` is Apache-2.0 and the owner is Apache Software 
foundation, the content would be [a dedicated 
license](https://www.apache.org/legal/src-headers.html#headers) specified by 
the ASF, otherwise, the license would be [the standard 
one](https://www.apache.org/foundation/license-faq.html#Apply-My-Software).
+**NOTE**: When the `SPDX-ID` is Apache-2.0 and the owner is Apache Software 
foundation, the content would
+be [a dedicated 
license](https://www.apache.org/legal/src-headers.html#headers) specified by 
the ASF, otherwise, the
+license would be [the standard 
one](https://www.apache.org/foundation/license-faq.html#Apply-My-Software).
 
 ## Supported File Types
 
-The `header check` command theoretically supports all kinds of file types, 
while the supported file types of `header fix` command can be found [in this 
YAML file](assets/languages.yaml). In the YAML file, if the language has a 
non-empty property `comment_style_id`, and the comment style id is declared in 
[the comment styles file](assets/styles.yaml), then the language is supported 
by `fix` command.
+The `header check` command theoretically supports all kinds of file types, 
while the supported file types
+of `header fix` command can be found [in this YAML 
file](assets/languages.yaml). In the YAML file, if the language has a
+non-empty property `comment_style_id`, and the comment style id is declared
+in [the comment styles file](assets/styles.yaml), then the language is 
supported by `fix` command.
 
 - [assets/languages.yaml](assets/languages.yaml)
 
@@ -286,27 +305,34 @@ The `header check` command theoretically supports all 
kinds of file types, while
     end: ' */'            # (iv)
   ```
 
-  1. The `comment_style_id` used in 
[assets/languages.yaml](assets/languages.yaml).
-  2. The leading characters of the starting of a block comment.
-  3. The leading characters of the middle lines of a block comment.
-  4. The leading characters of the ending line of a block comment.
+    1. The `comment_style_id` used in 
[assets/languages.yaml](assets/languages.yaml).
+    2. The leading characters of the starting of a block comment.
+    3. The leading characters of the middle lines of a block comment.
+    4. The leading characters of the ending line of a block comment.
 
 ## Technical Documentation
 
-- There is an [activity diagram](./docs/header_fix_logic.svg) explaining the 
implemented license header
-  fixing mechanism in-depth. The diagram's source file can be found 
[here](./docs/header_fix_logic.plantuml).
+- There is an [activity diagram](./docs/header_fix_logic.svg) explaining the 
implemented license header fixing mechanism
+  in-depth. The diagram's source file can be found 
[here](./docs/header_fix_logic.plantuml).
 
 ## Contribution
 
-- If you find any file type should be supported by the aforementioned 
configurations, but it's not listed there, feel free to [open a pull 
request](https://github.com/apache/skywalking-eyes/pulls) to add the 
configuration into the two files.
-- If you find the license template of an SPDX ID is not supported, feel free 
to [open a pull request](https://github.com/apache/skywalking-eyes/pulls) to 
add it into [the template folder](assets/header-templates).
+- If you find any file type should be supported by the aforementioned 
configurations, but it's not listed there, feel
+  free to [open a pull 
request](https://github.com/apache/skywalking-eyes/pulls) to add the 
configuration into the two
+  files.
+- If you find the license template of an SPDX ID is not supported, feel free
+  to [open a pull request](https://github.com/apache/skywalking-eyes/pulls) to 
add it
+  into [the template folder](assets/header-templates).
 
 ## License
 
 [Apache License 
2.0](https://github.com/apache/skywalking-eyes/blob/master/LICENSE)
 
 ## Contact Us
+
 * Submit [an issue](https://github.com/apache/skywalking/issues/new) by using 
[INFRA] as title prefix.
-* Mail list: **[email protected]**. Mail to 
[email protected], follow the reply to subscribe the mail 
list.
-* Join `skywalking` channel at [Apache 
Slack](http://s.apache.org/slack-invite). If the link is not working, find the 
latest one at [Apache INFRA 
WIKI](https://cwiki.apache.org/confluence/display/INFRA/Slack+Guest+Invites).
+* Mail list: **[email protected]**. Mail to 
[email protected], follow the reply to subscribe
+  the mail list.
+* Join `skywalking` channel at [Apache 
Slack](http://s.apache.org/slack-invite). If the link is not working, find the
+  latest one at [Apache INFRA 
WIKI](https://cwiki.apache.org/confluence/display/INFRA/Slack+Guest+Invites).
 * Twitter, [ASFSkyWalking](https://twitter.com/ASFSkyWalking)
diff --git a/commands/deps_resolve.go b/commands/deps_resolve.go
index 4a03927..9551fd0 100644
--- a/commands/deps_resolve.go
+++ b/commands/deps_resolve.go
@@ -19,17 +19,38 @@ package commands
 
 import (
        "fmt"
+       "os"
+       "regexp"
        "strings"
 
+       "github.com/apache/skywalking-eyes/license-eye/internal/logger"
        "github.com/spf13/cobra"
 
        "github.com/apache/skywalking-eyes/license-eye/pkg/deps"
 )
 
+var outDir string
+
+func init() {
+       DepsResolveCommand.PersistentFlags().StringVarP(&outDir, "output", "o", 
"", "the directory to output the resolved dependencies' licenses, if not set 
the dependencies' licenses won't be saved")
+}
+
+var fileNamePattern = regexp.MustCompile(`[^a-zA-Z0-9\\.\-]`)
+
 var DepsResolveCommand = &cobra.Command{
        Use:     "resolve",
        Aliases: []string{"r"},
        Long:    "resolves all dependencies of a module and their transitive 
dependencies",
+       PreRunE: func(cmd *cobra.Command, args []string) error {
+               if outDir == "" {
+                       return nil
+               }
+               if err := os.MkdirAll(outDir, 0700); err == nil || 
os.IsExist(err) {
+                       return nil
+               } else {
+                       return err
+               }
+       },
        RunE: func(cmd *cobra.Command, args []string) error {
                report := deps.Report{}
 
@@ -37,6 +58,12 @@ var DepsResolveCommand = &cobra.Command{
                        return err
                }
 
+               if outDir != "" {
+                       for _, result := range report.Resolved {
+                               writeLicense(result)
+                       }
+               }
+
                fmt.Println(report.String())
 
                if skipped := len(report.Skipped); skipped > 0 {
@@ -53,3 +80,19 @@ var DepsResolveCommand = &cobra.Command{
                return nil
        },
 }
+
+func writeLicense(result *deps.Result) {
+       filename := 
string(fileNamePattern.ReplaceAll([]byte(result.Dependency), []byte("-")))
+       filename = strings.TrimRight(outDir, "/") + "/license-" + filename + 
".txt"
+       file, err := os.Create(filename)
+       if err != nil {
+               logger.Log.Errorf("failed to create license file %v: %v", 
filename, err)
+               return
+       }
+       defer func(file *os.File) { _ = file.Close() }(file)
+       _, err = file.WriteString(result.LicenseContent)
+       if err != nil {
+               logger.Log.Errorf("failed to write license file, %v: %v", 
filename, err)
+               return
+       }
+}

Reply via email to