diff --git a/README.md b/README.md index ab54e35..4579dc6 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ However, some libraries have archived their source code repositories or have had | language | package manager | dependencies file (e.g.) | status | | -------- | ------------- | -- | :----: | | Dart | pub | pubspec.lock | :heavy_check_mark: | +| Erlang/Elixir | mix | mix.lock | :heavy_check_mark: | | Go | golang | go.mod | :heavy_check_mark: | | JavaScript | npm | package-lock.json | :heavy_check_mark: | | JavaScript | yarn | yarn.lock | :heavy_check_mark: | diff --git a/cmd/diagnose.go b/cmd/diagnose.go index d6fb137..79a5c59 100644 --- a/cmd/diagnose.go +++ b/cmd/diagnose.go @@ -15,6 +15,7 @@ import ( "github.com/aquasecurity/go-dep-parser/pkg/types" "github.com/fatih/color" dart "github.com/kyoshidajp/dep-doctor/cmd/dart/pub" + erlang_elixir "github.com/kyoshidajp/dep-doctor/cmd/erlang_elixir/hex" "github.com/kyoshidajp/dep-doctor/cmd/github" "github.com/kyoshidajp/dep-doctor/cmd/golang" "github.com/kyoshidajp/dep-doctor/cmd/nodejs" @@ -214,15 +215,16 @@ func (d Doctors) UnknownErrorMessage(packageManager string) string { var doctors = Doctors{ "bundler": ruby.NewBundlerDoctor(), - "yarn": nodejs.NewYarnDoctor(), + "cargo": rust.NewCargoDoctor(), + "cocoapods": swift.NewCococaPodsDoctor(), + "composer": php.NewComposerDoctor(), + "golang": golang.NewGolangDoctor(), + "npm": nodejs.NewNPMDoctor(), + "mix": erlang_elixir.NewMixDoctor(), "pip": python.NewPipDoctor(), "pipenv": python.NewPipenvDoctor(), "pub": dart.NewPubDoctor(), - "npm": nodejs.NewNPMDoctor(), - "composer": php.NewComposerDoctor(), - "golang": golang.NewGolangDoctor(), - "cargo": rust.NewCargoDoctor(), - "cocoapods": swift.NewCococaPodsDoctor(), + "yarn": nodejs.NewYarnDoctor(), } var diagnoseCmd = &cobra.Command{ diff --git a/cmd/erlang_elixir/hex/hex.go b/cmd/erlang_elixir/hex/hex.go new file mode 100644 index 0000000..0ea0294 --- /dev/null +++ b/cmd/erlang_elixir/hex/hex.go @@ -0,0 +1,52 @@ +package erlang_elixir + +import ( + "encoding/json" + "errors" + "fmt" + "io" + "net/http" +) + +const HEX_REGISTRY_API = "https://hex.pm/api/packages/%s" + +type HexRegistryResponse struct { + Meta struct { + Links struct { + GitHub string `json:"GitHub"` + } `json:"links"` + } `json:"meta"` +} + +type Hex struct { + name string +} + +func (g *Hex) fetchURLFromRegistry(client http.Client) (string, error) { + url := fmt.Sprintf(HEX_REGISTRY_API, g.name) + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return "", err + } + + resp, err := client.Do(req) + if err != nil { + return "", err + } + + defer resp.Body.Close() + if resp.StatusCode < 200 || 299 < resp.StatusCode { + m := fmt.Sprintf("Got status code: %d from %s", resp.StatusCode, url) + return "", errors.New(m) + } + + body, _ := io.ReadAll(resp.Body) + + var hex HexRegistryResponse + err = json.Unmarshal(body, &hex) + if err != nil { + return "", err + } + + return hex.Meta.Links.GitHub, nil +} diff --git a/cmd/erlang_elixir/hex/mix.go b/cmd/erlang_elixir/hex/mix.go new file mode 100644 index 0000000..a530d08 --- /dev/null +++ b/cmd/erlang_elixir/hex/mix.go @@ -0,0 +1,30 @@ +package erlang_elixir + +import ( + "net/http" + + "github.com/aquasecurity/go-dep-parser/pkg/hex/mix" + parser_io "github.com/aquasecurity/go-dep-parser/pkg/io" + "github.com/aquasecurity/go-dep-parser/pkg/types" +) + +type MixDoctor struct { + HTTPClient http.Client +} + +func NewMixDoctor() *MixDoctor { + client := &http.Client{} + return &MixDoctor{HTTPClient: *client} +} + +func (d *MixDoctor) Libraries(r parser_io.ReadSeekerAt) []types.Library { + p := &mix.Parser{} + libs, _, _ := p.Parse(r) + return libs +} + +func (d *MixDoctor) SourceCodeURL(lib types.Library) (string, error) { + hex := Hex{name: lib.Name} + url, err := hex.fetchURLFromRegistry(d.HTTPClient) + return url, err +} diff --git a/cmd/erlang_elixir/hex/testdata/mix.lock b/cmd/erlang_elixir/hex/testdata/mix.lock new file mode 100644 index 0000000..7ab92fc --- /dev/null +++ b/cmd/erlang_elixir/hex/testdata/mix.lock @@ -0,0 +1,7 @@ +%{ + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm", "7af5c7e09fe1d40f76c8e4f9dd2be7cebd83909f31fee7cd0e9eadc567da8353"}, + "credo": {:hex, :credo, "1.6.6", "f51f8d45db1af3b2e2f7bee3e6d3c871737bda4a91bff00c5eec276517d1a19c", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2.8", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "625520ce0984ee0f9f1f198165cd46fa73c1e59a17ebc520038b8fce056a5bdc"}, + "file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"}, + "jason": {:hex, :jason, "1.3.0", "fa6b82a934feb176263ad2df0dbd91bf633d4a46ebfdffea0c8ae82953714946", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "53fc1f51255390e0ec7e50f9cb41e751c260d065dcba2bf0d08dc51a4002c2ac"}, + "esaml": {:git, "https://github.com/firezone/esaml.git", "4294a3ac5262582144e117c10a1537287b6c1fe8", []}, +} \ No newline at end of file