Created
June 27, 2012 13:02
-
-
Save lluchs/3003943 to your computer and use it in GitHub Desktop.
Automatic github downloader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "io" | |
import "time" | |
func copySleep(dst io.Writer, src io.Reader, delay int, progress func(written int64)) (written int64, err error) { | |
// If the writer has a ReadFrom method, use it to do the copy. | |
// Avoids an allocation and a copy. | |
if rt, ok := dst.(io.ReaderFrom); ok { | |
return rt.ReadFrom(src) | |
} | |
// Similarly, if the reader has a WriteTo method, use it to do the copy. | |
if wt, ok := src.(io.WriterTo); ok { | |
return wt.WriteTo(dst) | |
} | |
buf := make([]byte, 32*1024) | |
for { | |
nr, er := src.Read(buf) | |
if nr > 0 { | |
nw, ew := dst.Write(buf[0:nr]) | |
if nw > 0 { | |
written += int64(nw) | |
} | |
if ew != nil { | |
err = ew | |
break | |
} | |
if nr != nw { | |
err = io.ErrShortWrite | |
break | |
} | |
} | |
if er == io.EOF { | |
break | |
} | |
if er != nil { | |
err = er | |
break | |
} | |
progress(written) | |
time.Sleep(time.Duration(delay) * time.Millisecond) | |
} | |
return written, err | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import "log" | |
import "fmt" | |
import "os" | |
import "strings" | |
import "net/http" | |
import "io" | |
import "io/ioutil" | |
import "archive/zip" | |
// change me! | |
const Branch = "master" | |
const GithubURL = "http://github.com/lluchs/Clinfinity/zipball/" | |
const prefixPathLength = 25 | |
const progressBarWidth = 50 | |
func main() { | |
clifiPath := "." | |
branch := Branch | |
download := true | |
var r *zip.Reader | |
var err error | |
// The first parameter can either be an archive that will be extracted (suffix '.zip') | |
// or a branch name. | |
if len(os.Args) > 1 { | |
if strings.HasSuffix(os.Args[1], ".zip") { | |
log.Printf("Using specified archive %s", os.Args[1]) | |
var rc *zip.ReadCloser | |
rc, err = zip.OpenReader(os.Args[1]) | |
defer rc.Close() | |
r = &rc.Reader | |
download = false | |
} else { | |
branch = os.Args[1] | |
} | |
} | |
if download { | |
downloadFile := createTempFile() | |
defer func() { | |
// close and remove the file | |
name := downloadFile.Name() | |
downloadFile.Close() | |
os.Remove(name) | |
}() | |
log.Printf("Downloading branch %s...", branch) | |
length := downloadArchive(downloadFile, branch) | |
log.Print("Download complete.") | |
r, err = zip.NewReader(downloadFile, length) | |
} | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Print("Extracting archive...") | |
// remove relevant archives | |
os.RemoveAll(clifiPath + "/Clinfinity.c4d") | |
os.RemoveAll(clifiPath + "/Clinfinity.c4f") | |
// progress | |
var total, i int64 = int64(len(r.File)), 0 | |
// loop over all files | |
for _, f := range r.File { | |
relPath := f.Name[prefixPathLength:] | |
// ignore files outside of relevant folders | |
if !strings.HasPrefix(relPath, "/Clinfinity") { continue } | |
// absolute file path | |
path := clifiPath + relPath | |
// create folders, if necessary | |
os.MkdirAll(basePath(path), 0644) | |
// don't do anything else with directories | |
if path[len(path) - 1] == '/' { continue } | |
// create file | |
dest, err := os.Create(path) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// open file in zip archive | |
rc, err := f.Open() | |
if err != nil { | |
log.Fatal(err) | |
} | |
// copy file content | |
_, err = io.Copy(dest, rc) | |
if err != nil { | |
log.Fatal(err) | |
} | |
rc.Close() | |
dest.Close() | |
// progress indicator | |
i++ | |
progressBar(i, total) | |
} | |
println() | |
log.Print("Done") | |
} | |
func createTempFile() *os.File { | |
// create temporary file | |
downloadFile, err := ioutil.TempFile("", "github-get") | |
if err != nil { | |
log.Fatal(err) | |
} | |
return downloadFile | |
} | |
func downloadArchive(file *os.File, branch string) int64 { | |
// download the specified branch | |
url := GithubURL + branch | |
resp, err := http.Get(url) | |
if err != nil { | |
log.Fatal(err) | |
} | |
defer resp.Body.Close() | |
progress := func(written int64) { | |
if resp.ContentLength != -1 { | |
progressBar(written, resp.ContentLength) | |
} | |
} | |
// read the response | |
written, err := copySleep(file, resp.Body, 10, progress) | |
if err != nil { | |
log.Fatal(err) | |
} | |
println() | |
return written | |
} | |
func basePath(path string) string { | |
lastSlash := strings.LastIndex(path, "/") | |
if lastSlash != -1 { | |
path = path[:lastSlash] | |
} | |
return path | |
} | |
func progressBar(current int64, total int64) { | |
bar := "[" | |
percent := 100 * current / total | |
tokens := progressBarWidth * current / total | |
var i int64 | |
for i = 0; i < progressBarWidth; i++ { | |
if i < tokens { | |
bar += "=" | |
} else { | |
bar += " " | |
} | |
} | |
bar += "]" | |
fmt.Printf("\r%s %d%%\r", bar, percent) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment