Help us shape the future of Go! Take the 2026 Go Developer Survey

project

package
v1.38.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package project provides cobra commands for managing project-based repository collections. A project is a logical grouping of related repositories (e.g., a product with multiple microservices).

Index

Constants

This section is empty.

Variables

View Source
var AddCmd = &cobra.Command{
	Use:   "add",
	Short: "Add a new project or repository to configuration",
	Long: `This command interactively adds a new project or adds a repository to an existing project.

You will be prompted for:
  - Project name (new or existing)
  - Repository URL (SSH or HTTPS)
  - Optional custom directory name

Example:
  eng project add                  # Interactive add
  eng project add -p MyProject     # Add a repo to the specified project`,
	Run: func(cmd *cobra.Command, args []string) {
		log.Start("Adding project configuration")

		projectFilter, _ := cmd.Flags().GetString("project")

		existingNames := config.GetProjectNames()

		var projectName string

		if projectFilter != "" {

			projectName = projectFilter
			found := false
			for _, name := range existingNames {
				if name == projectFilter {
					found = true
					break
				}
			}
			if !found {
				// Project doesn't exist, confirm creation
				var confirmCreate bool
				confirmCreate, err := ui.Confirm("Project '"+projectFilter+"' doesn't exist. Create it?", true)
				if err != nil {
					log.Error("Prompt failed: %s", err)
					return
				}
				if !confirmCreate {
					log.Info("Canceled.")
					return
				}
			}
		} else {

			options := append([]string{"[Create new project]"}, existingNames...)

			var selection string
			var err error
			selection, err = ui.Select("Select a project or create a new one:", options, "")
			if err != nil {
				log.Error("Prompt failed: %s", err)
				return
			}

			if selection == "[Create new project]" {
				projectName, err = ui.Input("Enter new project name:", "")
				if err != nil {
					log.Error("Prompt failed: %s", err)
					return
				}
				if projectName == "" {
					log.Error("Project name is required")
					return
				}
			} else {
				projectName = selection
			}
		}

		// Get repository URL
		var repoURL string
		var err error
		repoURL, err = ui.Input("Enter repository URL (SSH or HTTPS): (e.g., git@github.com:org/repo.git)", "")
		if err != nil {
			log.Error("Prompt failed: %s", err)
			return
		}
		if repoURL == "" {
			log.Error("Repository URL is required")
			return
		}

		defaultPath, err := config.RepoNameFromURL(repoURL)
		if err != nil {
			log.Error("Could not parse repository URL: %s", err)
			return
		}

		// Ask for optional custom path
		var customPath string
		customPath, err = ui.Input("Custom directory name (leave empty for default '"+defaultPath+"'):", "")
		if err != nil {
			log.Error("Prompt failed: %s", err)
			return
		}

		repo := config.ProjectRepo{
			URL:  repoURL,
			Path: customPath,
		}

		existingProject := config.GetProjectByName(projectName)
		if existingProject == nil {

			newProject := config.Project{
				Name:  projectName,
				Repos: []config.ProjectRepo{repo},
			}
			if err := config.AddProject(newProject); err != nil {
				log.Error("Failed to add project: %s", err)
				return
			}
			log.Success("Created new project '%s' with repository", projectName)
		} else {

			if err := config.AddRepoToProject(projectName, repo); err != nil {
				log.Error("Failed to add repository: %s", err)
				return
			}
			log.Success("Added repository to project '%s'", projectName)
		}

		// Ask if they want to add more
		var addMore bool
		addMore, err = ui.Confirm("Add another repository?", false)
		if err != nil {
			log.Error("Prompt failed: %s", err)
			return
		}

		if addMore {

			_ = cmd.Flags().Set("project", projectName)
			cmd.Run(cmd, args)
			return
		}

		log.Info("")
		log.Info("Run 'eng project setup' to clone the new repositories.")

		updatedProjects := config.GetProjects()
		for _, p := range updatedProjects {
			if p.Name == projectName {
				log.Info("")
				log.Info("Project '%s' now has %d repository(ies):", p.Name, len(p.Repos))
				for _, r := range p.Repos {
					path, _ := r.GetEffectivePath()
					log.Info("  - %s", path)
				}
				break
			}
		}
	},
}

AddCmd defines the cobra command for adding projects or repositories. It provides interactive prompts for configuration.

View Source
var FetchCmd = &cobra.Command{
	Use:   "fetch",
	Short: "Fetch updates for all project repositories",
	Long: `This command fetches updates from remote for all repositories in configured projects.

Example:
  eng project fetch                  # Fetch all projects
  eng project fetch -p MyProject     # Fetch only the specified project
  eng project fetch --dry-run        # Preview what would be fetched
  eng project fetch --force          # Force overwrite tags on conflicts`,
	Run: func(cmd *cobra.Command, args []string) {
		headerStyle := lipgloss.NewStyle().
			Bold(true).
			Foreground(theme.Primary).
			MarginBottom(1)
		if !ui.DisableProgress {
			fmt.Fprintln(log.Out, headerStyle.Render("🔍 Fetching Project Repositories"))
		}

		gitCfg := config.GetGitConfig()
		devPath := gitCfg.DevPath
		if devPath == "" {
			log.Error("Development folder path is not set. Use 'eng config git-dev-path' to set it.")
			return
		}

		dryRun, _ := cmd.Flags().GetBool("dry-run")
		force, _ := cmd.Flags().GetBool("force")
		projectFilter, _ := cmd.Flags().GetString("project")

		opts := internalProject.FetchOptions{
			DryRun:        dryRun,
			Force:         force,
			IsVerbose:     cmdutil.IsVerbose(cmd),
			ProjectFilter: projectFilter,
			DevPath:       os.ExpandEnv(devPath),
			Projects:      config.GetProjects(),
		}

		ctx := cmd.Context()
		if ctx == nil {
			ctx = cmdutil.FallbackContext()
		}

		internalProject.Fetch(ctx, opts)
	},
}

FetchCmd defines the cobra command for fetching all project repositories. It runs git fetch on all repositories in configured projects.

View Source
var ListCmd = &cobra.Command{
	Use:   "list",
	Short: "List configured projects and their repositories",
	Long: `This command displays all configured projects and their repositories.

Use the --verbose flag to see detailed information including:
  - Repository URLs
  - Clone status (✓ cloned / ✗ missing)
  - Local paths

Example:
  eng project list               # Show projects summary
  eng project list -v            # Show detailed repository information
  eng project list -p MyProject  # Show only the specified project`,
	Run: func(cmd *cobra.Command, args []string) {
		headerStyle := lipgloss.NewStyle().
			Bold(true).
			Foreground(theme.Primary).
			MarginBottom(1)
		if !ui.DisableProgress {
			fmt.Fprintln(log.Out, headerStyle.Render("📌 Project Repository Collections"))
		}

		gitCfg := config.GetGitConfig()
		projectFilter, _ := cmd.Flags().GetString("project")

		opts := internalProject.ListOptions{
			IsVerbose:     cmdutil.IsVerbose(cmd),
			ProjectFilter: projectFilter,
			DevPath:       gitCfg.DevPath,
			Projects:      config.GetProjects(),
		}

		internalProject.List(opts)
	},
}

ListCmd defines the cobra command for listing configured projects. It displays project names, repository counts, and clone status.

View Source
var ProjectCmd = &cobra.Command{
	Use:   "project",
	Short: "Manage project-based repository collections",
	Long: `This command facilitates the management of project-based repository collections.

A project is a logical grouping of related repositories. For example, you might have 
a project containing multiple microservices, or a shared infrastructure project.

Projects are stored in your development folder (configured via 'eng config git-dev-path'),
with each project having its own subdirectory containing all related repositories.

Example structure:
  ~/Development/
    MyProject/
      api/
      web/
      shared/
    Infrastructure/
      core/
      auth/`,
	Run: func(cmd *cobra.Command, args []string) {
		showInfo, _ := cmd.Flags().GetBool("info")
		isVerbose := cmdutil.IsVerbose(cmd)

		if showInfo {
			log.Info("Current project management configuration:")
			gitCfg := config.GetGitConfig()
			devPath := gitCfg.DevPath

			if devPath == "" {
				log.Warn("  Development Path: Not Set")
				log.Info("  Use 'eng config git-dev-path' to set your development folder path")
			} else {
				log.Info("  Development Path: %s", devPath)
			}

			projects := config.GetProjects()
			if len(projects) > 0 {
				log.Info("  Configured Projects: %d", len(projects))
			} else {
				log.Info("  Configured Projects: 0")
				log.Info("  Use 'eng project add' to configure a project")
			}
			return
		}

		if len(args) == 0 {
			log.Verbose(isVerbose, "No subcommand provided, showing help.")
			err := cmd.Help()
			cobra.CheckErr(err)
		} else {
			log.Verbose(isVerbose, "Subcommand '%s' provided.", args[0])
		}
	},
}

ProjectCmd serves as the base command for all project management operations. It groups subcommands like setup, list, add, remove, fetch, pull, and sync.

View Source
var PullCmd = &cobra.Command{
	Use:   "pull",
	Short: "Pull updates for all project repositories",
	Long: `This command pulls the latest changes from remote for all repositories in configured projects.

Note: Repositories with uncommitted changes will be skipped.

Example:
  eng project pull                  # Pull all projects
  eng project pull -p MyProject     # Pull only the specified project
  eng project pull --dry-run        # Preview what would be pulled`,
	Run: func(cmd *cobra.Command, args []string) {
		headerStyle := lipgloss.NewStyle().
			Bold(true).
			Foreground(theme.Primary).
			MarginBottom(1)
		if !ui.DisableProgress {
			fmt.Fprintln(log.Out, headerStyle.Render("📥 Pulling Project Repositories"))
		}

		gitCfg := config.GetGitConfig()
		devPath := gitCfg.DevPath
		if devPath == "" {
			log.Error("Development folder path is not set. Use 'eng config git-dev-path' to set it.")
			return
		}

		dryRun, _ := cmd.Flags().GetBool("dry-run")
		projectFilter, _ := cmd.Flags().GetString("project")

		opts := internalProject.PullOptions{
			DryRun:        dryRun,
			IsVerbose:     cmdutil.IsVerbose(cmd),
			ProjectFilter: projectFilter,
			DevPath:       os.ExpandEnv(devPath),
			Projects:      config.GetProjects(),
		}

		ctx := cmd.Context()
		if ctx == nil {
			ctx = cmdutil.FallbackContext()
		}

		internalProject.Pull(ctx, opts)
	},
}

PullCmd defines the cobra command for pulling all project repositories. It runs git pull on all repositories in configured projects.

View Source
var RemoveCmd = &cobra.Command{
	Use:   "remove",
	Short: "Remove a project or repository from configuration",
	Long: `This command removes a project or a repository from a project's configuration.

Note: This only removes the entry from your configuration. 
It does NOT delete any files from disk.

Example:
  eng project remove                  # Interactive removal
  eng project remove -p MyProject     # Remove from the specified project`,
	Run: func(cmd *cobra.Command, args []string) {
		log.Start("Removing project configuration")

		projectFilter, _ := cmd.Flags().GetString("project")

		projects := config.GetProjects()
		if len(projects) == 0 {
			log.Info("No projects configured.")
			return
		}

		existingNames := config.GetProjectNames()

		var projectName string

		if projectFilter != "" {

			projectName = projectFilter
			found := false
			for _, name := range existingNames {
				if name == projectFilter {
					found = true
					break
				}
			}
			if !found {
				log.Error("Project '%s' not found", projectFilter)
				return
			}
		} else {
			// Interactive project selection
			var err error
			projectName, err = ui.Select("Select a project:", existingNames, "")
			if err != nil {
				log.Error("Prompt failed: %s", err)
				return
			}
		}

		project := config.GetProjectByName(projectName)
		if project == nil {
			log.Error("Project '%s' not found", projectName)
			return
		}

		options := []string{"[Remove entire project]"}
		for _, repo := range project.Repos {
			path, err := repo.GetEffectivePath()
			if err != nil {
				path = repo.URL
			}
			options = append(options, path)
		}

		var selection string
		var err error
		selection, err = ui.Select("What would you like to remove?", options, "")
		if err != nil {
			log.Error("Prompt failed: %s", err)
			return
		}

		if selection == "[Remove entire project]" {
			// Confirm project removal
			var confirm bool
			confirm, err := ui.Confirm(
				"Remove project '"+projectName+"' with "+strconv.Itoa(len(project.Repos))+" repositories?",
				false,
			)
			if err != nil {
				log.Error("Prompt failed: %s", err)
				return
			}

			if !confirm {
				log.Info("Canceled.")
				return
			}

			if err := config.RemoveProject(projectName); err != nil {
				log.Error("Failed to remove project: %s", err)
				return
			}

			log.Success("Removed project '%s' from configuration", projectName)
			log.Info("Note: Files on disk were not deleted.")
		} else {
			// Find the repo URL for the selected path
			var repoURL string
			for _, repo := range project.Repos {
				path, _ := repo.GetEffectivePath()
				if path == selection {
					repoURL = repo.URL
					break
				}
			}

			if repoURL == "" {
				log.Error("Repository not found")
				return
			}

			// Confirm repo removal
			var confirm bool
			confirm, err := ui.Confirm("Remove repository '"+selection+"' from project '"+projectName+"'?", false)
			if err != nil {
				log.Error("Prompt failed: %s", err)
				return
			}

			if !confirm {
				log.Info("Canceled.")
				return
			}

			if err := config.RemoveRepoFromProject(projectName, repoURL); err != nil {
				log.Error("Failed to remove repository: %s", err)
				return
			}

			log.Success("Removed repository '%s' from project '%s'", selection, projectName)
			log.Info("Note: Files on disk were not deleted.")
		}
	},
}

RemoveCmd defines the cobra command for removing projects or repositories. It provides interactive prompts for safe removal.

View Source
var SetupCmd = &cobra.Command{
	Use:   "setup",
	Short: "Setup project directories and clone missing repositories",
	Long: `This command ensures all configured projects have their directory structure 
set up and all repositories are cloned.

It is safe to run multiple times - existing repositories will be skipped.
Use this command when:
  - Setting up a new development machine
  - A new repository has been added to a project's configuration
  - You want to verify all project repos are present

Example:
  eng project setup                  # Setup all projects
  eng project setup -p MyProject     # Setup only the specified project
  eng project setup --dry-run        # Preview what would be done`,
	Run: func(cmd *cobra.Command, args []string) {
		headerStyle := lipgloss.NewStyle().
			Bold(true).
			Foreground(theme.Primary).
			MarginBottom(1)
		if !ui.DisableProgress {
			fmt.Fprintln(log.Out, headerStyle.Render("🚀 Setting Up Project Repositories"))
		}

		gitCfg := config.GetGitConfig()
		devPath := gitCfg.DevPath
		if devPath == "" {
			log.Error("Development folder path is not set. Use 'eng config git-dev-path' to set it.")
			return
		}

		dryRun, _ := cmd.Flags().GetBool("dry-run")
		projectFilter, _ := cmd.Flags().GetString("project")

		opts := internalProject.SetupOptions{
			DryRun:        dryRun,
			IsVerbose:     cmdutil.IsVerbose(cmd),
			ProjectFilter: projectFilter,
			DevPath:       os.ExpandEnv(devPath),
			Projects:      config.GetProjects(),
		}

		ctx := cmd.Context()
		if ctx == nil {
			ctx = cmdutil.FallbackContext()
		}

		internalProject.Setup(ctx, opts)
	},
}

SetupCmd defines the cobra command for setting up project repositories.

View Source
var SyncCmd = &cobra.Command{
	Use:   "sync",
	Short: "Sync all project repositories (fetch + pull)",
	Long: `This command synchronizes all repositories in configured projects by:
  1. Fetching updates from remote (git fetch --all --prune)
  2. Pulling changes for the current branch (git pull)

Repositories with uncommitted changes will have fetch performed but pull will be skipped.

Example:
  eng project sync                  # Sync all projects
  eng project sync -p MyProject     # Sync only the specified project
  eng project sync --dry-run        # Preview what would be synced`,
	Run: func(cmd *cobra.Command, args []string) {
		headerStyle := lipgloss.NewStyle().
			Bold(true).
			Foreground(theme.Primary).
			MarginBottom(1)
		if !ui.DisableProgress {
			fmt.Fprintln(log.Out, headerStyle.Render("🔄 Syncing Project Repositories"))
		}

		gitCfg := config.GetGitConfig()
		devPath := gitCfg.DevPath
		if devPath == "" {
			log.Error("Development folder path is not set. Use 'eng config git-dev-path' to set it.")
			return
		}

		dryRun, _ := cmd.Flags().GetBool("dry-run")
		projectFilter, _ := cmd.Flags().GetString("project")

		opts := internalProject.SyncOptions{
			DryRun:        dryRun,
			IsVerbose:     cmdutil.IsVerbose(cmd),
			ProjectFilter: projectFilter,
			DevPath:       os.ExpandEnv(devPath),
			Projects:      config.GetProjects(),
		}

		ctx := cmd.Context()
		if ctx == nil {
			ctx = cmdutil.FallbackContext()
		}

		internalProject.Sync(ctx, opts)
	},
}

SyncCmd defines the cobra command for syncing all project repositories. It fetches and pulls all repositories in configured projects.

Functions

This section is empty.

Types

type ThreadSafeBuffer added in v1.13.0

type ThreadSafeBuffer struct {
	// contains filtered or unexported fields
}

ThreadSafeBuffer is a goroutine-safe bytes.Buffer.

func (*ThreadSafeBuffer) String added in v1.13.0

func (b *ThreadSafeBuffer) String() string

func (*ThreadSafeBuffer) Write added in v1.13.0

func (b *ThreadSafeBuffer) Write(p []byte) (n int, err error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL