From f640d6d11e052e209200c0766862f47dba514597 Mon Sep 17 00:00:00 2001 From: Yar Kravtsov Date: Sat, 24 May 2025 06:26:43 +0300 Subject: [PATCH] feat: add --remote flag to init command for adding origin remote --- README.md | 16 ++++++++++++++++ cmd/init.go | 14 +++++++++++++- internal/core/lnk.go | 8 ++++++++ internal/git/git.go | 13 +++++++++++++ test/integration_test.go | 21 +++++++++++++++++++++ 5 files changed, 71 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0fb5a6e..aee007c 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,16 @@ lnk init This creates `$XDG_CONFIG_HOME/lnk` (or `~/.config/lnk`) and initializes a Git repository. +### Initialize with remote + +```bash +lnk init --remote https://github.com/user/dotfiles.git +# or using short flag +lnk init -r git@github.com:user/dotfiles.git +``` + +This initializes the repository and adds the specified URL as the `origin` remote, allowing you to sync your dotfiles with a Git hosting service. + ### Add a file ```bash @@ -61,6 +71,9 @@ This: # Initialize lnk lnk init +# Initialize with remote for syncing with GitHub +lnk init --remote https://github.com/user/dotfiles.git + # Add some dotfiles lnk add ~/.bashrc lnk add ~/.vimrc @@ -72,6 +85,9 @@ lnk rm ~/.vimrc # Your files are now managed in ~/.config/lnk with Git history cd ~/.config/lnk git log --oneline + +# If you initialized with a remote, you can push changes +git push origin main ``` ## Error Handling diff --git a/cmd/init.go b/cmd/init.go index c8df04a..e931f16 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -12,15 +12,27 @@ var initCmd = &cobra.Command{ Short: "Initialize a new lnk repository", Long: "Creates the lnk directory and initializes a Git repository for managing dotfiles.", RunE: func(cmd *cobra.Command, args []string) error { + remote, _ := cmd.Flags().GetString("remote") + lnk := core.NewLnk() if err := lnk.Init(); err != nil { return fmt.Errorf("failed to initialize lnk: %w", err) } - fmt.Println("Initialized lnk repository") + + if remote != "" { + if err := lnk.AddRemote("origin", remote); err != nil { + return fmt.Errorf("failed to add remote: %w", err) + } + fmt.Printf("Initialized lnk repository with remote: %s\n", remote) + } else { + fmt.Println("Initialized lnk repository") + } + return nil }, } func init() { + initCmd.Flags().StringP("remote", "r", "", "Add origin remote URL to the repository") rootCmd.AddCommand(initCmd) } diff --git a/internal/core/lnk.go b/internal/core/lnk.go index a8bac29..3cb26c7 100644 --- a/internal/core/lnk.go +++ b/internal/core/lnk.go @@ -56,6 +56,14 @@ func (l *Lnk) Init() error { return nil } +// AddRemote adds a remote to the repository +func (l *Lnk) AddRemote(name, url string) error { + if err := l.git.AddRemote(name, url); err != nil { + return fmt.Errorf("failed to add remote %s: %w", name, err) + } + return nil +} + // Add moves a file to the repository and creates a symlink func (l *Lnk) Add(filePath string) error { // Validate the file diff --git a/internal/git/git.go b/internal/git/git.go index 3b3d249..fb21d57 100644 --- a/internal/git/git.go +++ b/internal/git/git.go @@ -33,6 +33,19 @@ func (g *Git) Init() error { return nil } +// AddRemote adds a remote to the repository +func (g *Git) AddRemote(name, url string) error { + cmd := exec.Command("git", "remote", "add", name, url) + cmd.Dir = g.repoPath + + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("git remote add failed: %w\nOutput: %s", err, string(output)) + } + + return nil +} + // AddAndCommit stages a file and commits it func (g *Git) AddAndCommit(filename, message string) error { // Stage the file diff --git a/test/integration_test.go b/test/integration_test.go index 9de4dc2..3148531 100644 --- a/test/integration_test.go +++ b/test/integration_test.go @@ -2,7 +2,9 @@ package test import ( "os" + "os/exec" "path/filepath" + "strings" "testing" "github.com/stretchr/testify/suite" @@ -202,6 +204,25 @@ func (suite *LnkIntegrationTestSuite) TestXDGConfigHomeFallback() { suite.DirExists(expectedDir) } +func (suite *LnkIntegrationTestSuite) TestInitWithRemote() { + // Test that init with remote adds the origin remote + err := suite.lnk.Init() + suite.Require().NoError(err) + + remoteURL := "https://github.com/user/dotfiles.git" + err = suite.lnk.AddRemote("origin", remoteURL) + suite.Require().NoError(err) + + // Verify the remote was added by checking git config + lnkDir := filepath.Join(suite.tempDir, "lnk") + cmd := exec.Command("git", "remote", "get-url", "origin") + cmd.Dir = lnkDir + + output, err := cmd.Output() + suite.Require().NoError(err) + suite.Equal(remoteURL, strings.TrimSpace(string(output))) +} + func TestLnkIntegrationSuite(t *testing.T) { suite.Run(t, new(LnkIntegrationTestSuite)) }