can now import repos and have more settings for creating new ones.

This commit is contained in:
2026-05-07 12:16:58 +02:00
parent dad82a79de
commit 39dd9ab9eb
99 changed files with 7442 additions and 131 deletions
+100
View File
@@ -271,6 +271,106 @@ func Branches(repoPath string) ([]Branch, error) {
return branches, nil
}
// SetDefaultBranch updates HEAD to point at the given branch name.
func SetDefaultBranch(repoPath, branch string) error {
_, err := run(repoPath, "symbolic-ref", "HEAD", "refs/heads/"+branch)
return err
}
// InitWithFiles creates an initial commit in a bare repo by:
// 1. git init in a temp dir → write files → commit → git push file://repoPath.
// Use this right after Init() when initReadme or initGitignore is requested.
func InitWithFiles(repoPath, branch, repoName, authorName, authorEmail string, initReadme, initGitignore bool) error {
tmpDir, err := os.MkdirTemp("", "fb-init-*")
if err != nil {
return fmt.Errorf("mktemp: %w", err)
}
defer os.RemoveAll(tmpDir)
env := []string{
"GIT_TERMINAL_PROMPT=0",
"HOME=/tmp",
"GIT_AUTHOR_NAME=" + authorName,
"GIT_AUTHOR_EMAIL=" + authorEmail,
"GIT_COMMITTER_NAME=" + authorName,
"GIT_COMMITTER_EMAIL=" + authorEmail,
}
initCmd := exec.Command("git", "init", tmpDir)
initCmd.Env = env
if out, err := initCmd.CombinedOutput(); err != nil {
return fmt.Errorf("git init: %w: %s", err, out)
}
// Point the working-tree HEAD at the desired branch before the first commit.
symRef := exec.Command("git", "-C", tmpDir, "symbolic-ref", "HEAD", "refs/heads/"+branch)
symRef.Env = env
symRef.Run()
if initReadme {
if err := os.WriteFile(filepath.Join(tmpDir, "README.md"), []byte(readmeContent(repoName)), 0644); err != nil {
return fmt.Errorf("write README: %w", err)
}
}
if initGitignore {
if err := os.WriteFile(filepath.Join(tmpDir, ".gitignore"), []byte(gitignoreContent()), 0644); err != nil {
return fmt.Errorf("write .gitignore: %w", err)
}
}
addCmd := exec.Command("git", "add", ".")
addCmd.Dir = tmpDir
addCmd.Env = env
if out, err := addCmd.CombinedOutput(); err != nil {
return fmt.Errorf("git add: %w: %s", err, out)
}
commitCmd := exec.Command("git", "commit", "-m", "Initial commit")
commitCmd.Dir = tmpDir
commitCmd.Env = env
if out, err := commitCmd.CombinedOutput(); err != nil {
return fmt.Errorf("git commit: %w: %s", err, out)
}
// Push to the bare repo via file:// — works on all git versions.
pushCmd := exec.Command("git", "push", "file://"+filepath.ToSlash(filepath.Clean(repoPath)), branch)
pushCmd.Dir = tmpDir
pushCmd.Env = env
if out, err := pushCmd.CombinedOutput(); err != nil {
return fmt.Errorf("git push: %w: %s", err, out)
}
return nil
}
// CloneRepo mirrors a remote HTTP/HTTPS git repository into destPath (bare).
func CloneRepo(srcURL, destPath string) error {
if !strings.HasPrefix(srcURL, "http://") && !strings.HasPrefix(srcURL, "https://") {
return errors.New("only http and https source URLs are supported")
}
env := []string{"GIT_TERMINAL_PROMPT=0", "HOME=/tmp"}
cmd := exec.Command("git", "clone", "--mirror", srcURL, destPath)
cmd.Env = env
if out, err := cmd.CombinedOutput(); err != nil {
// Scrub the URL (which may contain credentials) from the error.
msg := strings.ReplaceAll(string(out), srcURL, "<url>")
return fmt.Errorf("git clone: %w: %s", err, msg)
}
// Enable pushes over HTTP.
cfgCmd := exec.Command("git", "-C", destPath, "config", "http.receivepack", "true")
cfgCmd.Env = env
cfgCmd.Run()
return nil
}
func readmeContent(repoName string) string {
return fmt.Sprintf("# %s\n\n## Description\n\nAdd your project description here.\n\n## Getting Started\n\n### Prerequisites\n\nList your prerequisites here.\n\n### Installation\n\n1. Clone the repository\n2. Follow setup instructions\n\n## Usage\n\nDescribe how to use your project.\n\n## Contributing\n\nContributions are welcome! Please open an issue or pull request.\n\n## License\n\nThis project is licensed under the MIT License.\n", repoName)
}
func gitignoreContent() string {
return "# OS\n.DS_Store\nThumbs.db\n\n# Editor\n.vscode/\n.idea/\n*.swp\n*.swo\n\n# Logs\n*.log\nlogs/\n\n# Dependencies\nnode_modules/\nvendor/\n\n# Build artifacts\ndist/\nbuild/\n*.o\n*.a\n*.so\n"
}
func BlobCat(repoPath, ref, filePath string) ([]byte, error) {
return run(repoPath, "show", ref+":"+filePath)
}