[mirror] Scalable static site server for Git forges (like GitHub Pages)

Accept an output argument in `-get-blob`, `-get-manifest`, `-get-archive`.

Changed files
+30 -15
src
+30 -15
src/main.go
··· 81 } 82 } 83 84 func Main() { 85 printConfigEnvVars := flag.Bool("print-config-env-vars", false, 86 "print every recognized configuration environment variable and exit") ··· 91 noConfig := flag.Bool("no-config", false, 92 "run without configuration file (configure via environment variables)") 93 runMigration := flag.String("run-migration", "", 94 - "run a specific store migration (available: \"create-domain-markers\")") 95 getBlob := flag.String("get-blob", "", 96 - "write contents of `blob-ref` ('sha256-xxxxxxx...xxx') to stdout") 97 getManifest := flag.String("get-manifest", "", 98 - "write manifest for `site-name` (either 'domain.tld' or 'domain.tld/dir') to stdout as ProtoJSON") 99 getArchive := flag.String("get-archive", "", 100 - "write archive for `site-name` (either 'domain.tld' or 'domain.tld/dir') to stdout in tar format") 101 updateSite := flag.String("update-site", "", 102 - "update site for `site-name` (either 'domain.tld' or 'domain.tld/dir') from archive or repository URL") 103 flag.Parse() 104 105 var cliOperations int ··· 183 if err != nil { 184 log.Fatalln(err) 185 } 186 - 187 - io.Copy(os.Stdout, reader) 188 189 case *getManifest != "": 190 if err := ConfigureBackend(&config.Storage); err != nil { ··· 196 if err != nil { 197 log.Fatalln(err) 198 } 199 - fmt.Println(ManifestDebugJSON(manifest)) 200 201 case *getArchive != "": 202 if err := ConfigureBackend(&config.Storage); err != nil { ··· 209 if err != nil { 210 log.Fatalln(err) 211 } 212 - CollectTar(context.Background(), os.Stdout, manifest, manifestMtime) 213 214 case *updateSite != "": 215 if err := ConfigureBackend(&config.Storage); err != nil { 216 log.Fatalln(err) 217 } 218 219 - sourceURL, _ := url.Parse(flag.Arg(0)) 220 - if sourceURL == nil || *sourceURL == (url.URL{}) { 221 - log.Fatalln("update source must be provided as an argument") 222 } 223 224 - webRoot := *updateSite 225 - if !strings.Contains(webRoot, "/") { 226 - webRoot += "/.index" 227 } 228 229 var result UpdateResult ··· 232 if err != nil { 233 log.Fatalln(err) 234 } 235 236 var contentType string 237 switch { ··· 247 log.Fatalf("cannot determine content type from filename %q\n", sourceURL) 248 } 249 250 result = UpdateFromArchive(context.Background(), webRoot, contentType, file) 251 } else { 252 branch := "pages" 253 if sourceURL.Fragment != "" { 254 branch, sourceURL.Fragment = sourceURL.Fragment, "" 255 } 256 result = UpdateFromRepository(context.Background(), webRoot, sourceURL.String(), branch) 257 } 258
··· 81 } 82 } 83 84 + func fileOutputArg() (writer io.WriteCloser) { 85 + var err error 86 + if flag.NArg() == 0 { 87 + writer = os.Stdout 88 + } else { 89 + writer, err = os.Create(flag.Arg(0)) 90 + if err != nil { 91 + log.Fatalln(err) 92 + } 93 + } 94 + return 95 + } 96 + 97 func Main() { 98 printConfigEnvVars := flag.Bool("print-config-env-vars", false, 99 "print every recognized configuration environment variable and exit") ··· 104 noConfig := flag.Bool("no-config", false, 105 "run without configuration file (configure via environment variables)") 106 runMigration := flag.String("run-migration", "", 107 + "run a store `migration` (one of: create-domain-markers)") 108 getBlob := flag.String("get-blob", "", 109 + "write contents of `blob` ('sha256-xxxxxxx...xxx')") 110 getManifest := flag.String("get-manifest", "", 111 + "write manifest for `site` (either 'domain.tld' or 'domain.tld/dir') as ProtoJSON") 112 getArchive := flag.String("get-archive", "", 113 + "write archive for `site` (either 'domain.tld' or 'domain.tld/dir') in tar format") 114 updateSite := flag.String("update-site", "", 115 + "update `site` (either 'domain.tld' or 'domain.tld/dir') from archive or repository URL") 116 flag.Parse() 117 118 var cliOperations int ··· 196 if err != nil { 197 log.Fatalln(err) 198 } 199 + io.Copy(fileOutputArg(), reader) 200 201 case *getManifest != "": 202 if err := ConfigureBackend(&config.Storage); err != nil { ··· 208 if err != nil { 209 log.Fatalln(err) 210 } 211 + fmt.Fprintln(fileOutputArg(), ManifestDebugJSON(manifest)) 212 213 case *getArchive != "": 214 if err := ConfigureBackend(&config.Storage); err != nil { ··· 221 if err != nil { 222 log.Fatalln(err) 223 } 224 + CollectTar(context.Background(), fileOutputArg(), manifest, manifestMtime) 225 226 case *updateSite != "": 227 if err := ConfigureBackend(&config.Storage); err != nil { 228 log.Fatalln(err) 229 } 230 231 + if flag.NArg() != 1 { 232 + log.Fatalln("update source must be provided as the argument") 233 } 234 235 + sourceURL, err := url.Parse(flag.Arg(0)) 236 + if err != nil { 237 + log.Fatalln(err) 238 } 239 240 var result UpdateResult ··· 243 if err != nil { 244 log.Fatalln(err) 245 } 246 + defer file.Close() 247 248 var contentType string 249 switch { ··· 259 log.Fatalf("cannot determine content type from filename %q\n", sourceURL) 260 } 261 262 + webRoot := webRootArg(*updateSite) 263 result = UpdateFromArchive(context.Background(), webRoot, contentType, file) 264 } else { 265 branch := "pages" 266 if sourceURL.Fragment != "" { 267 branch, sourceURL.Fragment = sourceURL.Fragment, "" 268 } 269 + 270 + webRoot := webRootArg(*updateSite) 271 result = UpdateFromRepository(context.Background(), webRoot, sourceURL.String(), branch) 272 } 273