OLD | NEW |
---|---|
1 package main | 1 package main |
2 | 2 |
3 import ( | 3 import ( |
4 "bytes" | 4 "bytes" |
5 "crypto/md5" | 5 "crypto/md5" |
6 "database/sql" | 6 "database/sql" |
7 "encoding/base64" | 7 "encoding/base64" |
8 "encoding/json" | 8 "encoding/json" |
9 "flag" | 9 "flag" |
10 "fmt" | 10 "fmt" |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
91 "waterfall", "river", "breeze", "moon", "rain", "wind", "sea", " morning", | 91 "waterfall", "river", "breeze", "moon", "rain", "wind", "sea", " morning", |
92 "snow", "lake", "sunset", "pine", "shadow", "leaf", "dawn", "gli tter", | 92 "snow", "lake", "sunset", "pine", "shadow", "leaf", "dawn", "gli tter", |
93 "forest", "hill", "cloud", "meadow", "sun", "glade", "bird", "br ook", | 93 "forest", "hill", "cloud", "meadow", "sun", "glade", "bird", "br ook", |
94 "butterfly", "bush", "dew", "dust", "field", "fire", "flower", " firefly", | 94 "butterfly", "bush", "dew", "dust", "field", "fire", "flower", " firefly", |
95 "feather", "grass", "haze", "mountain", "night", "pond", "darkne ss", | 95 "feather", "grass", "haze", "mountain", "night", "pond", "darkne ss", |
96 "snowflake", "silence", "sound", "sky", "shape", "surf", "thunde r", | 96 "snowflake", "silence", "sound", "sky", "shape", "surf", "thunde r", |
97 "violet", "water", "wildflower", "wave", "water", "resonance", " sun", | 97 "violet", "water", "wildflower", "wave", "water", "resonance", " sun", |
98 "wood", "dream", "cherry", "tree", "fog", "frost", "voice", "pap er", | 98 "wood", "dream", "cherry", "tree", "fog", "frost", "voice", "pap er", |
99 "frog", "smoke", "star", | 99 "frog", "smoke", "star", |
100 } | 100 } |
101 | |
102 gitHash = "" | |
103 gitInfo = "" | |
101 ) | 104 ) |
102 | 105 |
103 // flags | 106 // flags |
104 var ( | 107 var ( |
105 useChroot = flag.Bool("use_chroot", false, "Run the compiled code in the schroot jail.") | 108 useChroot = flag.Bool("use_chroot", false, "Run the compiled code in the schroot jail.") |
106 port = flag.String("port", ":8000", "HTTP service address (e.g., ': 8000')") | 109 port = flag.String("port", ":8000", "HTTP service address (e.g., ': 8000')") |
107 ) | 110 ) |
108 | 111 |
109 // lineNumbers adds #line numbering to the user's code. | 112 // lineNumbers adds #line numbering to the user's code. |
110 func LineNumbers(c string) string { | 113 func LineNumbers(c string) string { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
156 } | 159 } |
157 workspaceTemplate, err = htemplate.ParseFiles( | 160 workspaceTemplate, err = htemplate.ParseFiles( |
158 filepath.Join(cwd, "templates/workspace.html"), | 161 filepath.Join(cwd, "templates/workspace.html"), |
159 filepath.Join(cwd, "templates/titlebar.html"), | 162 filepath.Join(cwd, "templates/titlebar.html"), |
160 filepath.Join(cwd, "templates/content.html"), | 163 filepath.Join(cwd, "templates/content.html"), |
161 ) | 164 ) |
162 if err != nil { | 165 if err != nil { |
163 panic(err) | 166 panic(err) |
164 } | 167 } |
165 | 168 |
169 // The git command returns output of the format: | |
170 // | |
171 // f672cead70404080a991ebfb86c38316a4589b23 2014-04-27 19:21:51 +0000 | |
172 // M include/core/SkDynamicAnnotations.h | |
mtklein
2014/04/28 15:06:20
Hey, I know this change...
| |
173 // M include/core/SkOnce.h | |
174 // M include/core/SkRefCnt.h | |
175 // | |
176 logOutput, err := doCmd(`git log --format=%H%x20%ai --name-status HEAD^. .HEAD`, true) | |
177 if err != nil { | |
178 panic(err) | |
179 } | |
180 logInfo := strings.Split(logOutput, " ") | |
181 gitHash = logInfo[0] | |
182 gitInfo = logInfo[1] + " " + logInfo[2] + " " + logInfo[0][0:6] | |
mtklein
2014/04/28 15:06:20
Looks like we just need the results of git log --f
jcgregorio
2014/04/28 15:11:57
Done.
| |
183 | |
166 // Connect to MySQL server. First, get the password from the metadata se rver. | 184 // Connect to MySQL server. First, get the password from the metadata se rver. |
167 // See https://developers.google.com/compute/docs/metadata#custom. | 185 // See https://developers.google.com/compute/docs/metadata#custom. |
168 req, err := http.NewRequest("GET", "http://metadata/computeMetadata/v1/i nstance/attributes/password", nil) | 186 req, err := http.NewRequest("GET", "http://metadata/computeMetadata/v1/i nstance/attributes/password", nil) |
169 if err != nil { | 187 if err != nil { |
170 panic(err) | 188 panic(err) |
171 } | 189 } |
172 client := http.Client{} | 190 client := http.Client{} |
173 req.Header.Add("X-Google-Metadata-Request", "True") | 191 req.Header.Add("X-Google-Metadata-Request", "True") |
174 if resp, err := client.Do(req); err == nil { | 192 if resp, err := client.Do(req); err == nil { |
175 password, err := ioutil.ReadAll(resp.Body) | 193 password, err := ioutil.ReadAll(resp.Body) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
214 hash CHAR(64) DEFAULT '' NOT NULL, | 232 hash CHAR(64) DEFAULT '' NOT NULL, |
215 hidden INTEGER DEFAULT 0 NOT NULL, | 233 hidden INTEGER DEFAULT 0 NOT NULL, |
216 | 234 |
217 FOREIGN KEY (name) REFERENCES workspace(name) | 235 FOREIGN KEY (name) REFERENCES workspace(name) |
218 )` | 236 )` |
219 _, err = db.Exec(sql) | 237 _, err = db.Exec(sql) |
220 log.Printf("Info: status creating sqlite table for workspace try : %q\n", err) | 238 log.Printf("Info: status creating sqlite table for workspace try : %q\n", err) |
221 } | 239 } |
222 } | 240 } |
223 | 241 |
242 // Titlebar is used in titlebar template expansion. | |
243 type Titlebar struct { | |
244 GitHash string | |
245 GitInfo string | |
246 } | |
247 | |
224 // userCode is used in template expansion. | 248 // userCode is used in template expansion. |
225 type userCode struct { | 249 type userCode struct { |
226 » Code string | 250 » Code string |
227 » Hash string | 251 » Hash string |
252 » Titlebar Titlebar | |
228 } | 253 } |
229 | 254 |
230 // expandToFile expands the template and writes the result to the file. | 255 // expandToFile expands the template and writes the result to the file. |
231 func expandToFile(filename string, code string, t *template.Template) error { | 256 func expandToFile(filename string, code string, t *template.Template) error { |
232 f, err := os.Create(filename) | 257 f, err := os.Create(filename) |
233 if err != nil { | 258 if err != nil { |
234 return err | 259 return err |
235 } | 260 } |
236 defer f.Close() | 261 defer f.Close() |
237 » return t.Execute(f, userCode{Code: code}) | 262 » return t.Execute(f, userCode{Code: code, Titlebar: Titlebar{GitHash: git Hash, GitInfo: gitInfo}}) |
238 } | 263 } |
239 | 264 |
240 // expandCode expands the template into a file and calculate the MD5 hash. | 265 // expandCode expands the template into a file and calculate the MD5 hash. |
241 func expandCode(code string) (string, error) { | 266 func expandCode(code string) (string, error) { |
242 h := md5.New() | 267 h := md5.New() |
243 h.Write([]byte(code)) | 268 h.Write([]byte(code)) |
244 hash := fmt.Sprintf("%x", h.Sum(nil)) | 269 hash := fmt.Sprintf("%x", h.Sum(nil)) |
245 // At this point we are running in skia/experimental/webtry, making cach e a | 270 // At this point we are running in skia/experimental/webtry, making cach e a |
246 // peer directory to skia. | 271 // peer directory to skia. |
247 // TODO(jcgregorio) Make all relative directories into flags. | 272 // TODO(jcgregorio) Make all relative directories into flags. |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
358 filename := match[1] | 383 filename := match[1] |
359 http.ServeFile(w, r, fmt.Sprintf("../../../inout/%s", filename)) | 384 http.ServeFile(w, r, fmt.Sprintf("../../../inout/%s", filename)) |
360 } | 385 } |
361 | 386 |
362 type Try struct { | 387 type Try struct { |
363 Hash string `json:"hash"` | 388 Hash string `json:"hash"` |
364 CreateTS string `json:"create_ts"` | 389 CreateTS string `json:"create_ts"` |
365 } | 390 } |
366 | 391 |
367 type Recent struct { | 392 type Recent struct { |
368 » Tries []Try | 393 » Tries []Try |
394 » Titlebar Titlebar | |
369 } | 395 } |
370 | 396 |
371 // recentHandler shows the last 20 tries. | 397 // recentHandler shows the last 20 tries. |
372 func recentHandler(w http.ResponseWriter, r *http.Request) { | 398 func recentHandler(w http.ResponseWriter, r *http.Request) { |
373 log.Printf("Recent Handler: %q\n", r.URL.Path) | 399 log.Printf("Recent Handler: %q\n", r.URL.Path) |
374 | 400 |
375 var err error | 401 var err error |
376 rows, err := db.Query("SELECT create_ts, hash FROM webtry ORDER BY creat e_ts DESC LIMIT 20") | 402 rows, err := db.Query("SELECT create_ts, hash FROM webtry ORDER BY creat e_ts DESC LIMIT 20") |
377 if err != nil { | 403 if err != nil { |
378 http.NotFound(w, r) | 404 http.NotFound(w, r) |
379 return | 405 return |
380 } | 406 } |
381 recent := []Try{} | 407 recent := []Try{} |
382 for rows.Next() { | 408 for rows.Next() { |
383 var hash string | 409 var hash string |
384 var create_ts time.Time | 410 var create_ts time.Time |
385 if err := rows.Scan(&create_ts, &hash); err != nil { | 411 if err := rows.Scan(&create_ts, &hash); err != nil { |
386 log.Printf("Error: failed to fetch from database: %q", e rr) | 412 log.Printf("Error: failed to fetch from database: %q", e rr) |
387 continue | 413 continue |
388 } | 414 } |
389 recent = append(recent, Try{Hash: hash, CreateTS: create_ts.Form at("2006-02-01")}) | 415 recent = append(recent, Try{Hash: hash, CreateTS: create_ts.Form at("2006-02-01")}) |
390 } | 416 } |
391 » if err := recentTemplate.Execute(w, Recent{Tries: recent}); err != nil { | 417 » if err := recentTemplate.Execute(w, Recent{Tries: recent, Titlebar: Titl ebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil { |
392 log.Printf("ERROR: Failed to expand template: %q\n", err) | 418 log.Printf("ERROR: Failed to expand template: %q\n", err) |
393 } | 419 } |
394 } | 420 } |
395 | 421 |
396 type Workspace struct { | 422 type Workspace struct { |
397 » Name string | 423 » Name string |
398 » Code string | 424 » Code string |
399 » Hash string | 425 » Hash string |
400 » Tries []Try | 426 » Tries []Try |
427 » Titlebar Titlebar | |
401 } | 428 } |
402 | 429 |
403 // newWorkspace generates a new random workspace name and stores it in the datab ase. | 430 // newWorkspace generates a new random workspace name and stores it in the datab ase. |
404 func newWorkspace() (string, error) { | 431 func newWorkspace() (string, error) { |
405 for i := 0; i < 10; i++ { | 432 for i := 0; i < 10; i++ { |
406 adj := workspaceNameAdj[rand.Intn(len(workspaceNameAdj))] | 433 adj := workspaceNameAdj[rand.Intn(len(workspaceNameAdj))] |
407 noun := workspaceNameNoun[rand.Intn(len(workspaceNameNoun))] | 434 noun := workspaceNameNoun[rand.Intn(len(workspaceNameNoun))] |
408 suffix := rand.Intn(1000) | 435 suffix := rand.Intn(1000) |
409 name := fmt.Sprintf("%s-%s-%d", adj, noun, suffix) | 436 name := fmt.Sprintf("%s-%s-%d", adj, noun, suffix) |
410 if _, err := db.Exec("INSERT INTO workspace (name) VALUES(?)", n ame); err == nil { | 437 if _, err := db.Exec("INSERT INTO workspace (name) VALUES(?)", n ame); err == nil { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
450 } | 477 } |
451 } | 478 } |
452 var code string | 479 var code string |
453 var hash string | 480 var hash string |
454 if len(tries) == 0 { | 481 if len(tries) == 0 { |
455 code = DEFAULT_SAMPLE | 482 code = DEFAULT_SAMPLE |
456 } else { | 483 } else { |
457 hash = tries[len(tries)-1].Hash | 484 hash = tries[len(tries)-1].Hash |
458 code, _ = getCode(hash) | 485 code, _ = getCode(hash) |
459 } | 486 } |
460 » » if err := workspaceTemplate.Execute(w, Workspace{Tries: tries, C ode: code, Name: name, Hash: hash}); err != nil { | 487 » » if err := workspaceTemplate.Execute(w, Workspace{Tries: tries, C ode: code, Name: name, Hash: hash, Titlebar: Titlebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil { |
461 log.Printf("ERROR: Failed to expand template: %q\n", err ) | 488 log.Printf("ERROR: Failed to expand template: %q\n", err ) |
462 } | 489 } |
463 } else if r.Method == "POST" { | 490 } else if r.Method == "POST" { |
464 name, err := newWorkspace() | 491 name, err := newWorkspace() |
465 if err != nil { | 492 if err != nil { |
466 http.Error(w, "Failed to create a new workspace.", 500) | 493 http.Error(w, "Failed to create a new workspace.", 500) |
467 return | 494 return |
468 } | 495 } |
469 http.Redirect(w, r, "/w/"+name, 302) | 496 http.Redirect(w, r, "/w/"+name, 302) |
470 } | 497 } |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
570 http.NotFound(w, r) | 597 http.NotFound(w, r) |
571 return | 598 return |
572 } | 599 } |
573 // Update 'code' with the code found in the database. | 600 // Update 'code' with the code found in the database. |
574 if err := db.QueryRow("SELECT code FROM webtry WHERE has h=?", hash).Scan(&code); err != nil { | 601 if err := db.QueryRow("SELECT code FROM webtry WHERE has h=?", hash).Scan(&code); err != nil { |
575 http.NotFound(w, r) | 602 http.NotFound(w, r) |
576 return | 603 return |
577 } | 604 } |
578 } | 605 } |
579 // Expand the template. | 606 // Expand the template. |
580 » » if err := indexTemplate.Execute(w, userCode{Code: code, Hash: ha sh}); err != nil { | 607 » » if err := indexTemplate.Execute(w, userCode{Code: code, Hash: ha sh, Titlebar: Titlebar{GitHash: gitHash, GitInfo: gitInfo}}); err != nil { |
581 log.Printf("ERROR: Failed to expand template: %q\n", err ) | 608 log.Printf("ERROR: Failed to expand template: %q\n", err ) |
582 } | 609 } |
583 } else if r.Method == "POST" { | 610 } else if r.Method == "POST" { |
584 w.Header().Set("Content-Type", "application/json") | 611 w.Header().Set("Content-Type", "application/json") |
585 buf := bytes.NewBuffer(make([]byte, 0, MAX_TRY_SIZE)) | 612 buf := bytes.NewBuffer(make([]byte, 0, MAX_TRY_SIZE)) |
586 n, err := buf.ReadFrom(r.Body) | 613 n, err := buf.ReadFrom(r.Body) |
587 if err != nil { | 614 if err != nil { |
588 reportTryError(w, r, err, "Failed to read a request body .", "") | 615 reportTryError(w, r, err, "Failed to read a request body .", "") |
589 return | 616 return |
590 } | 617 } |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
666 http.HandleFunc("/w/", workspaceHandler) | 693 http.HandleFunc("/w/", workspaceHandler) |
667 http.HandleFunc("/recent/", recentHandler) | 694 http.HandleFunc("/recent/", recentHandler) |
668 http.HandleFunc("/iframe/", iframeHandler) | 695 http.HandleFunc("/iframe/", iframeHandler) |
669 http.HandleFunc("/json/", tryInfoHandler) | 696 http.HandleFunc("/json/", tryInfoHandler) |
670 http.HandleFunc("/css/", cssHandler) | 697 http.HandleFunc("/css/", cssHandler) |
671 http.HandleFunc("/js/", jsHandler) | 698 http.HandleFunc("/js/", jsHandler) |
672 // TODO Break out /c/ as it's own handler. | 699 // TODO Break out /c/ as it's own handler. |
673 http.HandleFunc("/", mainHandler) | 700 http.HandleFunc("/", mainHandler) |
674 log.Fatal(http.ListenAndServe(*port, nil)) | 701 log.Fatal(http.ListenAndServe(*port, nil)) |
675 } | 702 } |
OLD | NEW |