Skip to content

Instantly share code, notes, and snippets.

@janbaer
Created November 6, 2020 09:09
Show Gist options
  • Save janbaer/ac58ee3da7bf693c144453eac934b0c3 to your computer and use it in GitHub Desktop.
Save janbaer/ac58ee3da7bf693c144453eac934b0c3 to your computer and use it in GitHub Desktop.

Revisions

  1. janbaer created this gist Nov 6, 2020.
    132 changes: 132 additions & 0 deletions find-refs.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,132 @@
    //usr/bin/env go run $0 $@ ; exit

    package main

    import (
    "encoding/json"
    "flag"
    "fmt"
    "io/ioutil"
    "os"
    "path/filepath"
    "strings"
    )

    type JSONFile struct {
    Services map[string]interface{}
    Dependencies map[string]interface{}
    DevDependencies map[string]interface{}
    }

    func main() {
    var rootDirectory, serviceName, packageName string
    currentDir, _ := os.Getwd()

    flag.StringVar(&rootDirectory, "dir", currentDir, "Pass the optional directory. Default is the current directory")
    flag.StringVar(&serviceName, "service", "", "The service to search for. You have to pass either the service or the package name")
    flag.StringVar(&packageName, "package", "", "The package to search for. You have to pass either the service or the package name")
    flag.Parse()

    if len(serviceName) == 0 && len(packageName) == 0 {
    flag.Usage()
    os.Exit(0)
    }

    if !verifyDirectoryExists(rootDirectory) {
    os.Exit(1)
    }

    if len(serviceName) != 0 {
    findService(serviceName, rootDirectory)
    } else {
    findPackage(packageName, rootDirectory)
    }
    }

    func findService(serviceName string, rootDirectory string) {
    filesToProcess, _ := getFilesToProcess(rootDirectory, true)

    fmt.Printf("Search for service %s in %d projects under %s\n", serviceName, len(filesToProcess), rootDirectory)

    numberOfHits := 0
    for _, jsonFilePath := range filesToProcess {
    parseJSONFile(jsonFilePath, func(jsonFile JSONFile) {
    if jsonFile.Services[serviceName] != nil {
    fmt.Println(extractProjectNameFromPath(jsonFilePath, 2))
    numberOfHits++
    }
    })
    }

    fmt.Printf("Found service %s in %d projects\n", serviceName, numberOfHits)
    }

    func findPackage(packageName string, rootDirectory string) {
    filesToProcess, _ := getFilesToProcess(rootDirectory, false)

    fmt.Printf("Search for package %s in %d projects under %s\n", packageName, len(filesToProcess), rootDirectory)

    numberOfHits := 0
    for _, jsonFilePath := range filesToProcess {
    parseJSONFile(jsonFilePath, func(jsonFile JSONFile) {
    packageVersion := jsonFile.Dependencies[packageName]
    if packageVersion == nil {
    packageVersion = jsonFile.DevDependencies[packageName]
    }
    if packageVersion != nil {
    fmt.Println(extractProjectNameFromPath(jsonFilePath, 1), packageVersion)
    numberOfHits++
    }
    })
    }

    fmt.Printf("Found package %s in %d projects\n", packageName, numberOfHits)
    }

    func parseJSONFile(jsonFilePath string, processParsedJSON func(config JSONFile)) {
    jsonAsBytes, _ := ioutil.ReadFile(jsonFilePath)

    var config JSONFile
    if err := json.Unmarshal(jsonAsBytes, &config); err != nil {
    fmt.Println("Error while parsing json from file", jsonFilePath, err)
    return
    }

    processParsedJSON(config)
    }

    func verifyDirectoryExists(directoryPath string) bool {
    stat, err := os.Stat(directoryPath)
    if err != nil {
    fmt.Printf("The specified directory %s does not exist!\n", directoryPath)
    return false
    }

    if !stat.IsDir() {
    fmt.Printf("The specified directory %s is not a directory!\n", directoryPath)
    return false
    }

    return true
    }

    func getFilesToProcess(rootDirectory string, searchInConfigFile bool) ([]string, error) {
    pattern := filepath.Join(rootDirectory, "**", "package.json")
    if searchInConfigFile {
    pattern = filepath.Join(rootDirectory, "**/**", "default.json")
    }

    filesToProcess, err := filepath.Glob(pattern)
    if err != nil {
    return nil, err
    }
    return filesToProcess, nil
    }

    func extractProjectNameFromPath(filePath string, levelsUp int) string {
    parts := strings.Split(filePath, "/")
    if len(parts) > 2 {
    return parts[len(parts)-levelsUp-1]
    }
    return filePath
    }