mirror of
https://github.com/gabrie30/ghorg.git
synced 2025-08-05 22:07:12 +02:00
Update/ghorgls (#450)
This commit is contained in:
parent
99958635bc
commit
08add68314
@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
### Added
|
||||
- GHORG_NO_DIR_SIZE flag to turn off directory size output which is now enabled by default
|
||||
- GHORG_STATS_ENABLED flag to track clone data over time, set to false by default
|
||||
- Added two new flags to the `ghorg ls` command: `--long` and `--total`, which provide additional information about the cloned directories.
|
||||
### Changed
|
||||
### Deprecated
|
||||
### Removed
|
||||
|
@ -351,7 +351,7 @@ Below are the headers and their descriptions. Note that these headers may change
|
||||
- **newClonesCount**: Sum of all new repos cloned
|
||||
- **existingResourcesPulledCount**: Sum of all repos that were pulled
|
||||
- **dirSizeInMB**: The size in megabytes of the output dir
|
||||
- **newCommits**: Sum of all new commits in all repos pulled or cloned
|
||||
- **newCommits**: Sum of all new commits in all repos pulled
|
||||
- **cloneInfosCount**: Number of clone Info messages
|
||||
- **cloneErrorsCount**: Number of clone Issues/Errors
|
||||
- **updateRemoteCount**: Number of remotes updated
|
||||
|
21
cmd/clone.go
21
cmd/clone.go
@ -19,6 +19,7 @@ import (
|
||||
"github.com/gabrie30/ghorg/configs"
|
||||
"github.com/gabrie30/ghorg/git"
|
||||
"github.com/gabrie30/ghorg/scm"
|
||||
"github.com/gabrie30/ghorg/utils"
|
||||
"github.com/korovkin/limiter"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@ -1090,7 +1091,7 @@ func printFinishedWithDirSize() {
|
||||
|
||||
func getCachedOrCalculatedOutputDirSizeInMb() (float64, error) {
|
||||
if !isDirSizeCached {
|
||||
dirSizeMB, err := calculateDirSizeInMb(outputDirAbsolutePath)
|
||||
dirSizeMB, err := utils.CalculateDirSizeInMb(outputDirAbsolutePath)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@ -1100,24 +1101,6 @@ func getCachedOrCalculatedOutputDirSizeInMb() (float64, error) {
|
||||
return cachedDirSizeMB, nil
|
||||
}
|
||||
|
||||
func calculateDirSizeInMb(path string) (float64, error) {
|
||||
var size int64
|
||||
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
size += info.Size()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
const bytesInMegabyte = 1000 * 1000
|
||||
return float64(size) / bytesInMegabyte, nil // Return size in Megabyte
|
||||
}
|
||||
|
||||
func filterByTargetReposPath(cloneTargets []scm.Repo) []scm.Repo {
|
||||
|
||||
_, err := os.Stat(os.Getenv("GHORG_TARGET_REPOS_PATH"))
|
||||
|
72
cmd/ls.go
72
cmd/ls.go
@ -1,11 +1,13 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gabrie30/ghorg/colorlog"
|
||||
"github.com/gabrie30/ghorg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -36,9 +38,76 @@ func listGhorgHome() {
|
||||
colorlog.PrintError("No clones found. Please clone some and try again.")
|
||||
}
|
||||
|
||||
longFormat := false
|
||||
totalFormat := false
|
||||
for _, arg := range os.Args {
|
||||
if arg == "-l" || arg == "--long" {
|
||||
longFormat = true
|
||||
}
|
||||
if arg == "-t" || arg == "--total" {
|
||||
totalFormat = true
|
||||
}
|
||||
}
|
||||
|
||||
if !longFormat && !totalFormat {
|
||||
for _, f := range files {
|
||||
if f.IsDir() {
|
||||
colorlog.PrintInfo(path + f.Name())
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var totalDirs int
|
||||
var totalSizeMB float64
|
||||
var totalRepos int
|
||||
|
||||
for _, f := range files {
|
||||
if f.IsDir() {
|
||||
colorlog.PrintInfo(path + f.Name())
|
||||
totalDirs++
|
||||
dirPath := filepath.Join(path, f.Name())
|
||||
dirSizeMB, err := utils.CalculateDirSizeInMb(dirPath)
|
||||
if err != nil {
|
||||
colorlog.PrintError(fmt.Sprintf("Error calculating directory size for %s: %v", dirPath, err))
|
||||
continue
|
||||
}
|
||||
totalSizeMB += dirSizeMB
|
||||
|
||||
// Count the number of directories with a depth of 1 inside
|
||||
subDirCount := 0
|
||||
subFiles, err := os.ReadDir(dirPath)
|
||||
if err != nil {
|
||||
colorlog.PrintError(fmt.Sprintf("Error reading directory contents for %s: %v", dirPath, err))
|
||||
continue
|
||||
}
|
||||
for _, subFile := range subFiles {
|
||||
if subFile.IsDir() {
|
||||
subDirCount++
|
||||
}
|
||||
}
|
||||
totalRepos += subDirCount
|
||||
|
||||
if !totalFormat || longFormat {
|
||||
if longFormat {
|
||||
if dirSizeMB > 1000 {
|
||||
dirSizeGB := dirSizeMB / 1000
|
||||
colorlog.PrintInfo(fmt.Sprintf("%-50s %10.2f GB %10d repos", dirPath, dirSizeGB, subDirCount))
|
||||
} else {
|
||||
colorlog.PrintInfo(fmt.Sprintf("%-50s %10.2f MB %10d repos", dirPath, dirSizeMB, subDirCount))
|
||||
}
|
||||
} else {
|
||||
colorlog.PrintInfo(path + f.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if totalFormat {
|
||||
if totalSizeMB > 1000 {
|
||||
totalSizeGB := totalSizeMB / 1000
|
||||
colorlog.PrintInfo(fmt.Sprintf("Total: %d directories, %.2f GB, %d repos", totalDirs, totalSizeGB, totalRepos))
|
||||
} else {
|
||||
colorlog.PrintInfo(fmt.Sprintf("Total: %d directories, %.2f MB, %d repos", totalDirs, totalSizeMB, totalRepos))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -60,7 +129,6 @@ func listGhorgDir(arg string) {
|
||||
colorlog.PrintError("No clones found. Please clone some and try again.")
|
||||
}
|
||||
|
||||
|
||||
for _, f := range files {
|
||||
if f.IsDir() {
|
||||
str := filepath.Join(path, f.Name())
|
||||
|
@ -351,6 +351,9 @@ func init() {
|
||||
reCloneCmd.Flags().BoolVar(&ghorgReCloneList, "list", false, "Prints reclone commands and optional descriptions to stdout then will exit 0. Does not obsfucate tokens, and is only available as a commandline argument")
|
||||
reCloneCmd.Flags().BoolVar(&ghorgReCloneEnvConfigOnly, "env-config-only", false, "GHORG_RECLONE_ENV_CONFIG_ONLY - Only use environment variables to set the configuration for all reclones.")
|
||||
|
||||
lsCmd.Flags().BoolP("long", "l", false, "Display detailed information about each clone directory, including size and number of repositories. Note: This may take longer depending on the number and size of the cloned organizations.")
|
||||
lsCmd.Flags().BoolP("total", "t", false, "Display total amounts of all repos cloned. Note: This may take longer depending on the number and size of the cloned organizations.")
|
||||
|
||||
rootCmd.AddCommand(lsCmd, versionCmd, cloneCmd, reCloneCmd, examplesCmd)
|
||||
}
|
||||
|
||||
|
@ -1,11 +0,0 @@
|
||||
package utils
|
||||
|
||||
// IsStringInSlice check if a string is in a given slice
|
||||
func IsStringInSlice(s string, sl []string) bool {
|
||||
for i := range sl {
|
||||
if sl[i] == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
34
utils/utils.go
Normal file
34
utils/utils.go
Normal file
@ -0,0 +1,34 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// IsStringInSlice check if a string is in a given slice
|
||||
func IsStringInSlice(s string, sl []string) bool {
|
||||
for i := range sl {
|
||||
if sl[i] == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func CalculateDirSizeInMb(path string) (float64, error) {
|
||||
var size int64
|
||||
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
size += info.Size()
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
const bytesInMegabyte = 1000 * 1000
|
||||
return float64(size) / bytesInMegabyte, nil // Return size in Megabyte
|
||||
}
|
Loading…
Reference in New Issue
Block a user