aboutsummaryrefslogtreecommitdiff
path: root/tools/git-bootstrap/main.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tools/git-bootstrap/main.go234
1 files changed, 234 insertions, 0 deletions
diff --git a/tools/git-bootstrap/main.go b/tools/git-bootstrap/main.go
new file mode 100644
index 0000000..23041ac
--- /dev/null
+++ b/tools/git-bootstrap/main.go
@@ -0,0 +1,234 @@
+package main
+
+import (
+ "flag"
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "path"
+ "strings"
+ "time"
+)
+
+const (
+ defaultLicense = `Copyright (c) %d %s
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+`
+)
+
+const (
+ forgeBaseURL = "https://git.fcuny.net"
+)
+
+var (
+ publicRepo = flag.Bool("public", false, "create a public repository at git.fcuny.net")
+ userEmail = flag.String("email", "franck@fcuny.net", "the author email that will be used for user.email")
+ userName = flag.String("username", "Franck Cuny", "the author name that will be used for user.name")
+)
+
+// GitRepo is the repository
+type GitRepo struct {
+ Name string
+ Path string
+}
+
+func init() {
+ flag.Parse()
+ flag.Usage = func() {
+ fmt.Fprintf(os.Stderr, "Usage: %s\n", os.Args[0])
+ flag.PrintDefaults()
+ }
+}
+
+func main() {
+ if flag.Arg(0) != "" {
+ path := flag.Arg(0)
+ if _, err := os.Stat(path); err != nil {
+ if os.IsNotExist(err) {
+ if err = os.Mkdir(path, 0766); err != nil {
+ log.Fatalf("Failed to create directory %s: %v", path, err)
+ }
+ }
+ if err = os.Chdir(path); err != nil {
+ log.Fatalf("Failed to change working directory to %s: %v", path, err)
+ }
+ }
+ }
+ repo, err := newRepository()
+
+ if err != nil {
+ log.Fatalf("Failed to get working directory for the repository: %v", err)
+ }
+
+ repo.Create()
+ repo.SetUser()
+ repo.InitialCommit()
+ repo.AddLicense()
+ repo.AddReadme()
+ repo.Commit()
+}
+
+func newRepository() (GitRepo, error) {
+ cwd, err := os.Getwd()
+ if err != nil {
+ return GitRepo{}, err
+ }
+
+ baseName := path.Base(cwd)
+ repo := GitRepo{
+ Name: baseName,
+ Path: cwd,
+ }
+ return repo, nil
+}
+
+// Run runs a git command
+func (r *GitRepo) Run(args []string) ([]string, error) {
+ out, err := exec.Command("git", args...).Output()
+ if err != nil {
+ return []string{}, err
+ }
+ return strings.Split(string(out), "\n"), nil
+}
+
+// Create creates a git repository
+func (r *GitRepo) Create() {
+ if _, err := os.Stat(".git"); err != nil {
+ if os.IsNotExist(err) {
+ _, err := r.Run([]string{"init"})
+ if err != nil {
+ log.Fatalf("Error while creating the repository: %v", err)
+ }
+ } else {
+ log.Fatalf("Unexpected error: %v", err)
+ }
+ }
+}
+
+// SetUser sets the correct username and email in .git/config
+func (r *GitRepo) SetUser() {
+ config, err := r.Run([]string{"config", "--local", "user.name"})
+ if err != nil || config[0] != *userName {
+ if _, err := r.Run([]string{"config", "--local", "user.name", *userName}); err != nil {
+ log.Printf("failed to set the username to %s: %v", *userName, err)
+ }
+ }
+
+ config, err = r.Run([]string{"config", "--local", "user.email"})
+ if err != nil || config[0] != *userEmail {
+ if _, err := r.Run([]string{"config", "--local", "user.email", *userEmail}); err != nil {
+ log.Printf("failed to set the email to %s: %v", *userEmail, err)
+ }
+ }
+}
+
+// InitialCommit creates the initial commit in the new repository
+func (r *GitRepo) InitialCommit() {
+ if _, err := os.Stat(".git/refs/heads/main"); err != nil {
+ if os.IsNotExist(err) {
+ _, err := r.Run([]string{"commit", "--allow-empty", "-m", "Initial commit\n\nThis commit is empty on purpose."})
+ if err != nil {
+ log.Fatalf("Error while creating the initial commit: %v", err)
+ }
+ }
+ }
+}
+
+// AddLicense adds a license file to the repository
+func (r *GitRepo) AddLicense() {
+ licenseFiles := []string{"LICENSE", "license", "LICENSE.txt", "license.txt"}
+ licenseExists := skipIfExist(licenseFiles)
+
+ if licenseExists {
+ return
+ }
+
+ head := []byte(fmt.Sprintf(defaultLicense, time.Now().Year(), *userName))
+ f, err := os.Create("LICENSE.txt")
+ if err != nil {
+ log.Fatalf("Error while creating the license file: %v", err)
+ }
+ defer f.Close()
+
+ _, err = f.Write(head)
+ if err != nil {
+ log.Fatalf("Error while writing the license file: %v", err)
+ }
+}
+
+// AddReadme adds a README to the repository
+func (r *GitRepo) AddReadme() {
+ readmeFiles := []string{"README", "README.txt", "README.md", "README.org"}
+ readmeExists := skipIfExist(readmeFiles)
+
+ if readmeExists {
+ return
+ }
+
+ head := []byte(fmt.Sprintf("#+TITLE: %s", r.Name))
+ f, err := os.Create("README.org")
+ if err != nil {
+ log.Fatalf("Error while creating the README file: %v", err)
+ }
+ defer f.Close()
+ _, err = f.Write(head)
+ if err != nil {
+ log.Fatalf("Error while writing the README file: %v", err)
+ }
+}
+
+//Commit commit the files to the repository
+func (r *GitRepo) Commit() {
+ filesAdded := []string{}
+ for _, file := range []string{"README.org", "LICENSE.txt"} {
+ skipFile := false
+ if _, err := os.Stat(file); err != nil {
+ if os.IsNotExist(err) {
+ skipFile = true
+ } else {
+ log.Fatalf("Error while committing %s: %v", file, err)
+ }
+ }
+ if skipFile {
+ continue
+ }
+ _, err := r.Run([]string{"add", file})
+ if err != nil {
+ log.Fatalf("Error while adding %s: %v", file, err)
+ }
+ filesAdded = append(filesAdded, file)
+ }
+ commitMessage := fmt.Sprintf("Add %s", strings.Join(filesAdded, ", "))
+ if _, err := r.Run([]string{"commit", "-m", commitMessage}); err != nil {
+ log.Fatalf("Error while committing the base files: %v", err)
+ }
+}
+
+func skipIfExist(fileNames []string) bool {
+ for _, fileName := range fileNames {
+ _, err := os.Stat(fileName)
+ if err == nil {
+ return true
+ }
+ }
+ return false
+}