Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/azdo_help_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -1039,6 +1039,22 @@ Configure default repository for this directory
-v, --view view the current default repository
```

### `azdo repo show [ORGANIZATION/]PROJECT/REPO_ID_OR_NAME [flags]`

Show repository details

```
-q, --jq expression Filter JSON output using a jq expression
--json fields[=*] Output JSON with the specified fields. Prefix a field with '-' to exclude it.
-t, --template string Format JSON output using a Go template; see "azdo help formatting"
```

Aliases

```
view, status
```

## `azdo security <command> [flags]`

Work with Azure DevOps security.
Expand Down
1 change: 1 addition & 0 deletions docs/azdo_repo.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Work with Azure DevOps Git repositories.
* [azdo repo list](./azdo_repo_list.md)
* [azdo repo restore](./azdo_repo_restore.md)
* [azdo repo set-default](./azdo_repo_set-default.md)
* [azdo repo show](./azdo_repo_show.md)

### ALIASES

Expand Down
50 changes: 50 additions & 0 deletions docs/azdo_repo_show.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
## Command `azdo repo show`

```
azdo repo show [ORGANIZATION/]PROJECT/REPO_ID_OR_NAME [flags]
```

Display the details of a single Azure DevOps Git repository.

The repository is identified by name or ID. The organization segment is optional when a
default organization is configured.


### Options


* `-q`, `--jq` `expression`

Filter JSON output using a jq expression

* `--json` `fields`

Output JSON with the specified fields. Prefix a field with &#39;-&#39; to exclude it.

* `-t`, `--template` `string`

Format JSON output using a Go template; see &#34;azdo help formatting&#34;


### ALIASES

- `view`
- `status`

### JSON Fields

`_links`, `defaultBranch`, `id`, `isDisabled`, `isFork`, `isInMaintenance`, `name`, `parentRepository`, `project`, `properties`, `remoteUrl`, `size`, `sshUrl`, `url`, `validRemoteUrls`, `webUrl`

### Examples

```bash
# Show a repository by name
azdo repo show Fabrikam/my-repo

# Show a repository by ID
azdo repo show myorg/Fabrikam/00000000-0000-0000-0000-000000000000
```

### See also

* [azdo repo](./azdo_repo.md)
2 changes: 2 additions & 0 deletions internal/cmd/repo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/tmeckel/azdo-cli/internal/cmd/repo/list"
"github.com/tmeckel/azdo-cli/internal/cmd/repo/restore"
"github.com/tmeckel/azdo-cli/internal/cmd/repo/setdefault"
"github.com/tmeckel/azdo-cli/internal/cmd/repo/show"
"github.com/tmeckel/azdo-cli/internal/cmd/util"
)

Expand Down Expand Up @@ -44,5 +45,6 @@ func NewCmdRepo(ctx util.CmdContext) *cobra.Command {
cmd.AddCommand(create.NewCmd(ctx))
cmd.AddCommand(delete.NewCmd(ctx))
cmd.AddCommand(edit.NewCmd(ctx))
cmd.AddCommand(show.NewCmd(ctx))
return cmd
}
174 changes: 174 additions & 0 deletions internal/cmd/repo/show/show.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package show

import (
_ "embed"
"fmt"

"github.com/MakeNowJust/heredoc/v2"
"github.com/microsoft/azure-devops-go-api/azuredevops/v7/git"
"github.com/spf13/cobra"
"go.uber.org/zap"

"github.com/tmeckel/azdo-cli/internal/cmd/util"
"github.com/tmeckel/azdo-cli/internal/template"
)

type showOptions struct {
targetArg string
exporter util.Exporter
}

//go:embed show.tpl
var showTpl string

func NewCmd(ctx util.CmdContext) *cobra.Command {
opts := &showOptions{}

cmd := &cobra.Command{
Use: "show [ORGANIZATION/]PROJECT/REPO_ID_OR_NAME",
Short: "Show repository details",
Long: heredoc.Doc(`
Display the details of a single Azure DevOps Git repository.

The repository is identified by name or ID. The organization segment is optional when a
default organization is configured.
`),
Example: heredoc.Doc(`
# Show a repository by name
azdo repo show Fabrikam/my-repo

# Show a repository by ID
azdo repo show myorg/Fabrikam/00000000-0000-0000-0000-000000000000
`),
Aliases: []string{"view", "status"},
Args: util.ExactArgs(1, "target argument is required and must be in the form [ORGANIZATION/]PROJECT/REPO_ID_OR_NAME"),
RunE: func(cmd *cobra.Command, args []string) error {
opts.targetArg = args[0]
return runShow(ctx, opts)
},
}

util.AddJSONFlags(cmd, &opts.exporter, []string{
"id",
"name",
"defaultBranch",
"remoteUrl",
"sshUrl",
"webUrl",
"url",
"project",
"parentRepository",
"size",
"isDisabled",
"isFork",
"isInMaintenance",
"validRemoteUrls",
"properties",
"_links",
})

return cmd
}

func runShow(cmdCtx util.CmdContext, opts *showOptions) error {
ios, err := cmdCtx.IOStreams()
if err != nil {
return err
}
ios.StartProgressIndicator()
defer ios.StopProgressIndicator()

scope, err := util.ParseProjectTargetWithDefaultOrganization(cmdCtx, opts.targetArg)
if err != nil {
return util.FlagErrorWrap(err)
}
if len(scope.Targets) == 0 {
return util.FlagErrorf("repository target is required")
}
repoIDOrName := scope.Targets[0]
if repoIDOrName == "" {
return util.FlagErrorf("repository target is required")
}

gitClient, err := cmdCtx.ClientFactory().Git(cmdCtx.Context(), scope.Organization)
if err != nil {
return fmt.Errorf("failed to create git client: %w", err)
}

zap.L().Debug(
"fetching repository",
zap.String("organization", scope.Organization),
zap.String("project", scope.Project),
zap.String("repository", repoIDOrName),
)

repo, err := gitClient.GetRepository(cmdCtx.Context(), git.GetRepositoryArgs{
RepositoryId: &repoIDOrName,
Project: &scope.Project,
})
if err != nil {
return fmt.Errorf("failed to get repository: %w", err)
}
if repo == nil {
return fmt.Errorf("repository %q not found", repoIDOrName)
}

if opts.exporter != nil {
ios.StopProgressIndicator()
return opts.exporter.Write(ios, repo)
}

ios.StopProgressIndicator()

t := template.New(
ios.Out,
ios.TerminalWidth(),
ios.ColorEnabled(),
).
WithTheme(ios.TerminalTheme()).
WithFuncs(map[string]any{
"hasBool": func(v *bool) bool { return v != nil },
"hasText": template.HasText,
"parent": func(repository *git.GitRepository) string {
if repository == nil || repository.IsFork == nil || !*repository.IsFork || repository.ParentRepository == nil {
return ""
}
parent := repository.ParentRepository
name := template.StringOrEmpty(parent.Name)
if parent.Id == nil {
return name
}
if name == "" {
return parent.Id.String()
}
return fmt.Sprintf("%s (%s)", name, parent.Id.String())
},
"s": template.StringOrEmpty,
"b": template.BoolString,
"u": template.UUIDString,
"size": func(size *uint64) string {
if size == nil {
return ""
}

const unit = 1024
value := float64(*size)
units := []string{"B", "KB", "MB", "GB"}
unitIndex := 0
for value >= unit && unitIndex < len(units)-1 {
value /= unit
unitIndex++
}
if unitIndex == 0 {
return fmt.Sprintf("%d B", *size)
}
return fmt.Sprintf("%.1f %s", value, units[unitIndex])
},
})

if err := t.Parse(showTpl); err != nil {
return err
}

return t.ExecuteData(repo)
}
13 changes: 13 additions & 0 deletions internal/cmd/repo/show/show.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{{bold "url:"}} {{hyperlink (s .Url) (s .Url)}}
{{bold "id:"}} {{u .Id}}
{{bold "name:"}} {{s .Name}}
{{bold "project:"}} {{s .Project.Name}}{{if hasText (u .Project.Id)}} ({{u .Project.Id}}){{end}}
{{if hasText (s .DefaultBranch)}}{{bold "default branch:"}} {{s .DefaultBranch}}{{end}}
{{bold "remote url:"}} {{s .RemoteUrl}}
{{bold "ssh url:"}} {{s .SshUrl}}
{{bold "web url:"}} {{s .WebUrl}}
{{bold "is fork:"}} {{b .IsFork}}
{{if hasText (parent .)}}{{bold " parent:"}} {{parent .}}{{end}}
{{if hasBool .IsDisabled}}{{bold "is disabled:"}} {{b .IsDisabled}}{{end}}
{{if hasBool .IsInMaintenance}}{{bold "is in maintenance:"}} {{b .IsInMaintenance}}{{end}}
{{if .Size}}{{bold "size:"}} {{size .Size}}{{end}}
Loading
Loading