github.com/driusan/dgit@v0.0.0-20221118233547-f39f0c15edbb/git/init.go (about) 1 package git 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "path/filepath" 8 ) 9 10 type InitOptions struct { 11 Quiet bool 12 Bare bool 13 14 Template File 15 16 // Not implemented 17 SeparateGitDir File 18 19 // Not implemented 20 Shared os.FileMode 21 } 22 23 func Init(c *Client, opts InitOptions, dir string) (*Client, error) { 24 if dir == "" { 25 dir2, err := os.Getwd() 26 if err != nil { 27 return nil, err 28 } 29 dir = dir2 30 } 31 32 if err := os.MkdirAll(dir, 0755); err != nil { 33 return nil, err 34 } 35 36 reinit := false 37 if !opts.Bare { 38 if File(dir + "/.git").Exists() { 39 reinit = true 40 } else if err := os.Mkdir(dir+"/.git", 0755); err != nil { 41 return nil, err 42 } 43 if c != nil { 44 // These must be absolute to be sure that filepath.Rel 45 // will work when cloning. 46 gd, err := filepath.Abs(filepath.Join(dir, ".git")) 47 if err != nil { 48 return nil, err 49 } 50 wd, err := filepath.Abs(dir) 51 if err != nil { 52 return nil, err 53 } 54 c.GitDir = GitDir(gd) 55 c.WorkDir = WorkDir(wd) 56 57 od, err := filepath.Abs(c.GetObjectsDir().String()) 58 if err != nil { 59 return nil, err 60 } 61 c.ObjectDir = od 62 } else { 63 c2, err := NewClient(dir+"/.git", dir) 64 if err != nil { 65 return nil, err 66 } 67 od, err := filepath.Abs(c2.ObjectDir) 68 if err != nil { 69 return nil, err 70 } 71 c2.ObjectDir = od 72 c = c2 73 } 74 } else { 75 if c != nil { 76 c.GitDir = GitDir(dir) 77 c.ObjectDir = c.GetObjectsDir().String() 78 } else { 79 c2, err := NewClient(dir, "") 80 if err != nil { 81 return nil, err 82 } 83 c = c2 84 } 85 } 86 87 // These are all the directories created by a clean "git init" 88 // with the canonical git implementation 89 if err := os.MkdirAll(filepath.Join(c.ObjectDir, "pack"), 0755); err != nil { 90 return nil, err 91 } 92 if err := os.MkdirAll(filepath.Join(c.ObjectDir, "info"), 0755); err != nil { 93 return nil, err 94 } 95 if err := os.MkdirAll(c.GitDir.String()+"/info", 0755); err != nil { 96 // FIXME: Should have exclude file in it 97 return nil, err 98 } 99 if err := os.MkdirAll(c.GitDir.String()+"/hooks", 0755); err != nil { 100 // FIXME: Should have sample hooks in it. 101 return nil, err 102 } 103 if err := os.MkdirAll(c.GitDir.String()+"/branches", 0755); err != nil { 104 return nil, err 105 } 106 if err := os.MkdirAll(c.GitDir.String()+"/refs/heads", 0755); err != nil { 107 return nil, err 108 } 109 if err := os.MkdirAll(c.GitDir.String()+"/refs/tags", 0755); err != nil { 110 return nil, err 111 } 112 113 bareConf := "bare = false" 114 if opts.Bare { 115 bareConf = "bare = true" 116 } 117 118 if c.GitDir.File("HEAD").Exists() { 119 reinit = true 120 } else if err := c.GitDir.WriteFile("HEAD", []byte("ref: refs/heads/master\n"), 0644); err != nil { 121 return nil, err 122 } 123 124 if c.GitDir.File("config").Exists() { 125 reinit = true 126 } else if err := c.GitDir.WriteFile("config", []byte("[core]\n\trepositoryformatversion = 0\n\t"+bareConf+"\n"), 0644); err != nil { 127 return nil, err 128 } 129 if c.GitDir.File("description").Exists() { 130 reinit = true 131 } else if err := c.GitDir.WriteFile("description", []byte("Unnamed repository; edit this file 'description' to name the repository.\n"), 0644); err != nil { 132 return nil, err 133 } 134 if !opts.Quiet { 135 dir, err := filepath.Abs(c.GitDir.String()) 136 if err != nil { 137 return c, err 138 } 139 if reinit { 140 fmt.Printf("Reinitialized existing Git repository in %v/\n", dir) 141 } else { 142 fmt.Printf("Initialized empty Git repository in %v/\n", dir) 143 } 144 } 145 146 if opts.Template != "" { 147 err := filepath.Walk(opts.Template.String(), func(path string, info os.FileInfo, err error) error { 148 if err != nil { 149 return err 150 } 151 path, err = filepath.Rel(opts.Template.String(), path) 152 if err != nil { 153 return err 154 } 155 156 if info.IsDir() { 157 os.MkdirAll(filepath.Join(c.GitDir.String(), path), 0777) 158 } else { 159 if c.GitDir.File(File(path)).Exists() { 160 return nil 161 } 162 newFile, err := c.GitDir.Create(File(path)) 163 if err != nil { 164 return err 165 } 166 defer newFile.Close() 167 f, err := os.Open(filepath.Join(opts.Template.String(), path)) 168 if err != nil { 169 return err 170 } 171 defer f.Close() 172 _, err = io.Copy(newFile, f) 173 if err != nil { 174 return err 175 } 176 } 177 178 return nil 179 }) 180 181 return c, err 182 } 183 184 return c, nil 185 }