this repo has no description

legit: add repo creation

Changed files
+161 -12
legit
+15 -7
legit/db/init.go
··· 17 17 } 18 18 19 19 _, err = db.Exec(` 20 - create table if not exists public_keys ( 21 - id integer primary key autoincrement, 22 - did text not null, 23 - name text not null, 24 - key text not null, 25 - unique(did, name, key)) 26 - `) 20 + create table if not exists public_keys ( 21 + id integer primary key autoincrement, 22 + did text not null, 23 + name text not null, 24 + key text not null, 25 + unique(did, name, key) 26 + ); 27 + create table if not exists repos ( 28 + id integer primary key autoincrement, 29 + did text not null, 30 + name text not null, 31 + description text not null, 32 + unique(did, name) 33 + ) 34 + `) 27 35 if err != nil { 28 36 return nil, err 29 37 }
+25
legit/db/repo.go
··· 1 + package db 2 + 3 + func (d *DB) AddRepo(did string, name string, description string) error { 4 + _, err := d.db.Exec("insert into repos (did, name, description) values (?, ?, ?)", did, name, description) 5 + if err != nil { 6 + return err 7 + } 8 + return nil 9 + } 10 + 11 + func (d *DB) RemoveRepo(did string) error { 12 + _, err := d.db.Exec("delete from repos where did = ?", did) 13 + if err != nil { 14 + return err 15 + } 16 + return nil 17 + } 18 + 19 + func (d *DB) UpdateRepo(did string, name string, description string) error { 20 + _, err := d.db.Exec("update repos set name = ?, description = ? where did = ?", name, description, did) 21 + if err != nil { 22 + return err 23 + } 24 + return nil 25 + }
+33
legit/git/repo.go
··· 1 + package git 2 + 3 + import ( 4 + "errors" 5 + "fmt" 6 + "os" 7 + "path/filepath" 8 + 9 + gogit "github.com/go-git/go-git/v5" 10 + "github.com/go-git/go-git/v5/config" 11 + ) 12 + 13 + func InitBare(path string) error { 14 + parent := filepath.Dir(path) 15 + 16 + if err := os.MkdirAll(parent, 0755); errors.Is(err, os.ErrExist) { 17 + return fmt.Errorf("error creating user directory: %w", err) 18 + } 19 + 20 + repository, err := gogit.PlainInit(path, true) 21 + if err != nil { 22 + return err 23 + } 24 + 25 + err = repository.CreateBranch(&config.Branch{ 26 + Name: "main", 27 + }) 28 + if err != nil { 29 + return fmt.Errorf("creating branch: %w", err) 30 + } 31 + 32 + return nil 33 + }
+5
legit/routes/handler.go
··· 51 51 r.Get("/login", h.Login) 52 52 r.Get("/static/{file}", h.ServeStatic) 53 53 54 + r.Route("/repo", func(r chi.Router) { 55 + r.Get("/new", h.NewRepo) 56 + r.Put("/new", h.NewRepo) 57 + }) 58 + 54 59 r.Route("/settings", func(r chi.Router) { 55 60 r.Get("/keys", h.Keys) 56 61 r.Put("/keys", h.Keys)
+39 -4
legit/routes/routes.go
··· 2 2 3 3 import ( 4 4 "compress/gzip" 5 + "errors" 5 6 "fmt" 6 7 "html/template" 7 8 "log" ··· 15 16 16 17 "github.com/dustin/go-humanize" 17 18 "github.com/go-chi/chi/v5" 19 + "github.com/go-git/go-git/v5/plumbing" 18 20 "github.com/icyphox/bild/legit/config" 19 21 "github.com/icyphox/bild/legit/db" 20 22 "github.com/icyphox/bild/legit/git" ··· 100 102 fmt.Println(path) 101 103 gr, err := git.Open(path, "") 102 104 if err != nil { 103 - h.Write404(w) 104 - return 105 + if errors.Is(err, plumbing.ErrReferenceNotFound) { 106 + h.t.ExecuteTemplate(w, "empty", nil) 107 + return 108 + } else { 109 + h.Write404(w) 110 + return 111 + } 105 112 } 106 113 commits, err := gr.Commits() 107 114 if err != nil { ··· 436 443 } 437 444 438 445 func (h *Handle) Keys(w http.ResponseWriter, r *http.Request) { 439 - 440 446 switch r.Method { 441 447 case http.MethodGet: 442 448 // TODO: fetch keys from db ··· 457 463 458 464 // TODO: add did here 459 465 if err := h.db.AddPublicKey("did:ashtntnashtx", name, key); err != nil { 460 - h.WriteOOBNotice(w, "keys", "Failed to add key") 466 + h.WriteOOBNotice(w, "keys", "Failed to add key.") 461 467 log.Printf("adding public key: %s", err) 462 468 return 463 469 } ··· 466 472 return 467 473 } 468 474 } 475 + 476 + func (h *Handle) NewRepo(w http.ResponseWriter, r *http.Request) { 477 + switch r.Method { 478 + case http.MethodGet: 479 + if err := h.t.ExecuteTemplate(w, "new", nil); err != nil { 480 + log.Println(err) 481 + return 482 + } 483 + case http.MethodPut: 484 + name := r.FormValue("name") 485 + description := r.FormValue("description") 486 + 487 + // TODO: Get handle from session. We need this to construct the repository path. 488 + err := git.InitBare(filepath.Join(h.c.Repo.ScanPath, "example.com", name)) 489 + if err != nil { 490 + h.WriteOOBNotice(w, "repo", "Error creating repo. Try again later.") 491 + return 492 + } 493 + 494 + err = h.db.AddRepo("did:ashtntnashtx", name, description) 495 + if err != nil { 496 + h.WriteOOBNotice(w, "repo", "Error creating repo. Try again later.") 497 + return 498 + } 499 + 500 + w.Header().Set("HX-Redirect", fmt.Sprintf("/@example.com/%s", name)) 501 + w.WriteHeader(http.StatusOK) 502 + } 503 + }
+1 -1
legit/routes/util.go
··· 26 26 func uniqueName(r *http.Request) string { 27 27 user := chi.URLParam(r, "user") 28 28 name := chi.URLParam(r, "name") 29 - return fmt.Sprintf("@%s/%s", user, name) 29 + return fmt.Sprintf("%s/%s", user, name) 30 30 } 31 31 32 32 func getDisplayName(name string) string {
+11
legit/templates/empty.html
··· 1 + {{ define "empty" }} 2 + <html> 3 + {{ template "head" . }} 4 + 5 + <body> 6 + <main> 7 + <p>This is an empty Git repository. Push some commits here.</p> 8 + </main> 9 + </body> 10 + </html> 11 + {{ end }}
+32
legit/templates/new.html
··· 1 + {{ define "new" }} 2 + <html> 3 + {{ template "head" . }} 4 + 5 + <body> 6 + <main> 7 + <h1>create a new repository</h1> 8 + <form> 9 + <p> 10 + Give your Git repository a name and, optionally, a 11 + description. 12 + </p> 13 + <div id="repo"></div> 14 + <div> 15 + <label for="name">Name</label> 16 + <input type="text" id="name" name="name" placeholder="" /> 17 + <label for="description">Description</label> 18 + <input 19 + type="text" 20 + id="description" 21 + name="description" 22 + placeholder="" 23 + /> 24 + </div> 25 + <button hx-put="/repo/new" hx-swap="none" type="submit"> 26 + Submit 27 + </button> 28 + </form> 29 + </main> 30 + </body> 31 + </html> 32 + {{ end }}