github.com/Xenoex/gopm@v0.6.5/cmd/serve.go (about) 1 // Copyright 2013 gopm authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"): you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations 13 // under the License. 14 15 package cmd 16 17 // import ( 18 // "errors" 19 // "fmt" 20 // "github.com/Unknwon/com" 21 // "github.com/gpmgo/gopm/doc" 22 // "github.com/syndtr/goleveldb/leveldb" 23 // "github.com/syndtr/goleveldb/leveldb/opt" 24 // "io/ioutil" 25 // "net/http" 26 // "net/url" 27 // "os" 28 // "os/exec" 29 // "path/filepath" 30 // "strconv" 31 // "strings" 32 // "time" 33 // ) 34 35 // var ( 36 // dbDir = "~/.gopm/db" 37 // ) 38 39 // const ( 40 // STOP = iota 41 // LOCALRUN 42 // RUNNING 43 // ) 44 45 // var CmdServe = &Command{ 46 // UsageLine: "serve [:port]", 47 // Short: "serve for package search", 48 // Long: ` 49 // serve provide a web service to search packages, download packages 50 51 // The serve flags are: 52 53 // -l 54 // only service for localhost ip 55 // `, 56 // } 57 58 // func init() { 59 // CmdServe.Run = runServe 60 // CmdServe.Flags = map[string]bool{ 61 // "-l": false, 62 // } 63 // } 64 65 // func printServePrompt(flag string) { 66 // switch flag { 67 // case "-l": 68 // com.ColorLog("[INFO] You enabled start a service only localhost.\n") 69 // } 70 // } 71 72 // // Not implemented 73 // func autoPort() string { 74 // return "8991" 75 // } 76 77 // func exePath() (string, error) { 78 // file, err := exec.LookPath(os.Args[0]) 79 // if err != nil { 80 // return "", err 81 // } 82 83 // return filepath.Abs(file) 84 // } 85 86 // // search packages 87 // func runServe(cmd *Command, args []string) { 88 // // Check flags. 89 // num := checkFlags(cmd.Flags, args, printServePrompt) 90 // if num == -1 { 91 // return 92 // } 93 // args = args[num:] 94 95 // var listen string 96 // var port string 97 // if cmd.Flags["-l"] { 98 // listen += "127.0.0.1" 99 // port = autoPort() 100 // } else { 101 // listen += "0.0.0.0" 102 // port = "8991" 103 // } 104 105 // // Check length of arguments. 106 // if len(args) >= 1 { 107 // port = args[0] 108 // } 109 110 // err := startService(listen, port) 111 // if err != nil { 112 // com.ColorLog("[ERRO] %v\n", err) 113 // } 114 // } 115 116 // func splitWord(word string, res *map[string]bool) { 117 // for i, _ := range word { 118 // for j, _ := range word[i:] { 119 // w := word[i : i+j+1] 120 // (*res)[w] = true 121 // } 122 // } 123 // return 124 // } 125 126 // func splitPkgName(pkgName string) (res map[string]bool) { 127 // //var src string 128 // ps := strings.Split(pkgName, "/") 129 // if len(ps) > 1 { 130 // ps = ps[1:] 131 // } 132 133 // res = make(map[string]bool) 134 // res[strings.Join(ps, "/")] = true 135 // for _, w := range ps { 136 // splitWord(w, &res) 137 // } 138 // return 139 // } 140 141 // func splitSynopsis(synopsis string) map[string]bool { 142 // res := make(map[string]bool) 143 // ss := strings.Fields(synopsis) 144 // for _, s := range ss { 145 // res[s] = true 146 // } 147 // return res 148 // } 149 150 // var ( 151 // ro *opt.ReadOptions = &opt.ReadOptions{} 152 // wo *opt.WriteOptions = &opt.WriteOptions{} 153 // ) 154 155 // func dbGet(key string) (string, error) { 156 // v, err := db.Get([]byte(key), ro) 157 // return string(v), err 158 // } 159 160 // func dbPut(key string, value string) error { 161 // //fmt.Println("put ", key, ": ", value) 162 // return db.Put([]byte(key), []byte(value), wo) 163 // } 164 165 // func batchPut(batch *leveldb.Batch, key string, value string) error { 166 // //fmt.Println("put ", key, ": ", value) 167 // batch.Put([]byte(key), []byte(value)) 168 // return nil 169 // } 170 171 // func getServeHost() string { 172 // return "localhost" 173 // } 174 175 // func getServePort() string { 176 // return "8991" 177 // } 178 179 // // for exernal of serve to add node to db 180 // func saveNode(nod *doc.Node) error { 181 // urlPath := fmt.Sprintf("http://%v:%v/add", getServeHost(), getServePort()) 182 // resp, err := http.PostForm(urlPath, 183 // url.Values{"importPath": {nod.ImportPath}, 184 // "synopsis": {nod.Synopsis}, 185 // "downloadURL": {nod.DownloadURL}, 186 // "isGetDeps": {strconv.FormatBool(nod.IsGetDeps)}, 187 // "type": {nod.Type}, 188 // "value": {nod.Value}}) 189 190 // if err != nil { 191 // com.ColorLog("[ERRO] Fail to save node[ %s ]\n", err) 192 // return err 193 // } 194 // defer resp.Body.Close() 195 196 // if resp.StatusCode == 200 { 197 // return nil 198 // } 199 // return errors.New("save node failed with " + resp.Status) 200 // } 201 202 // // for inetrnal of serve to add node to db 203 // func addNode(nod *doc.Node) error { 204 // batch := new(leveldb.Batch) 205 // strLastId, err := dbGet("lastId") 206 // if err != nil { 207 // if err == leveldb.ErrNotFound { 208 // strLastId = "0" 209 // err = batchPut(batch, "lastId", strLastId) 210 // } else { 211 // return err 212 // } 213 // } 214 // if err != nil { 215 // return err 216 // } 217 218 // lastId, err := strconv.ParseInt(strLastId, 0, 64) 219 // if err != nil { 220 // return err 221 // } 222 223 // nodKey := fmt.Sprintf("index:%v", nod.ImportPath) 224 225 // id, err := dbGet(nodKey) 226 // if err != nil { 227 // if err == leveldb.ErrNotFound { 228 // id = fmt.Sprintf("%v", lastId+1) 229 // err = batchPut(batch, "lastId", id) 230 // if err == nil { 231 // err = batchPut(batch, nodKey, id) 232 // } 233 // if err == nil { 234 // err = batchPut(batch, "pkg:"+id, nod.ImportPath) 235 // } 236 // if err == nil { 237 // err = batchPut(batch, "desc:"+id, nod.Synopsis) 238 // } 239 // if err == nil { 240 // err = batchPut(batch, "down:"+id, nod.DownloadURL) 241 // } 242 // if err == nil { 243 // err = batchPut(batch, "deps:"+id, strconv.FormatBool(nod.IsGetDeps)) 244 // } 245 246 // // save totals 247 // total, err := dbGet("total") 248 // if err != nil { 249 // if err == leveldb.ErrNotFound { 250 // total = "1" 251 // } else { 252 // return err 253 // } 254 // } else { 255 // totalInt, err := strconv.ParseInt(total, 0, 64) 256 // if err != nil { 257 // return err 258 // } 259 // totalInt = totalInt + 1 260 // total = fmt.Sprintf("%v", totalInt) 261 // } 262 263 // err = batchPut(batch, "total", total) 264 // } else { 265 // return err 266 // } 267 // } 268 269 // if err != nil { 270 // return err 271 // } 272 273 // // save vers 274 // vers, err := dbGet("ver:" + id) 275 // needSplit := (err == leveldb.ErrNotFound) 276 // if err != nil { 277 // if err != leveldb.ErrNotFound { 278 // return err 279 // } 280 // } else { 281 // return nil 282 // } 283 284 // if vers == "" { 285 // //fmt.Println(nod) 286 // vers = nod.VerString() 287 // } else { 288 // if !strings.Contains(vers, nod.VerString()) { 289 // vers = vers + "," + nod.VerString() 290 // } else { 291 // return nil 292 // } 293 // } 294 295 // err = batchPut(batch, "ver:"+id, vers) 296 // if err != nil { 297 // return err 298 // } 299 300 // if !needSplit { 301 // return nil 302 // } 303 304 // // indexing package name 305 // keys := splitPkgName(nod.ImportPath) 306 // for key, _ := range keys { 307 // err = batchPut(batch, fmt.Sprintf("key:%v:%v", strings.ToLower(key), id), "") 308 // if err != nil { 309 // return err 310 // } 311 // } 312 313 // if nod.Synopsis != "" { 314 // fields := splitSynopsis(nod.Synopsis) 315 // for field, _ := range fields { 316 // err = batchPut(batch, fmt.Sprintf("key:%v:%v", strings.ToLower(field), id), "") 317 // if err != nil { 318 // return err 319 // } 320 // } 321 // } 322 323 // return db.Write(batch, wo) 324 // } 325 326 // func rmPkg(nod *doc.Node) { 327 328 // } 329 330 // var db *leveldb.DB 331 332 // // service should be run 333 // func AutoRun() error { 334 // s, _, _ := runningStatus() 335 // if s == STOP { 336 // // current path 337 // curPath, err := os.Getwd() 338 // if err != nil { 339 // return err 340 // } 341 342 // attr := &os.ProcAttr{ 343 // Dir: curPath, 344 // Env: os.Environ(), 345 // //Files: []*os.File{nil, nil, nil}, 346 // Files: []*os.File{os.Stdin, os.Stdout, os.Stderr}, 347 // } 348 349 // p, err := exePath() 350 // if err != nil { 351 // return err 352 // } 353 354 // //com.ColorLog("[INFO] now is starting search daemon ...\n") 355 // _, err = os.StartProcess(p, []string{"gopm", "serve", "-l"}, attr) 356 // if err != nil { 357 // return err 358 // } 359 // time.Sleep(time.Second) 360 // } 361 // return nil 362 // } 363 364 // func runningStatus() (int, int, int) { 365 // pFile, err := getPidPath() 366 // if err != nil { 367 // return STOP, 0, 0 368 // } 369 370 // contentByte, err := ioutil.ReadFile(pFile) 371 // if err != nil { 372 // return STOP, 0, 0 373 // } 374 // content := string(contentByte) 375 // if len(content) < 0 || !strings.Contains(content, ",") { 376 // return STOP, 0, 0 377 // } 378 // cs := strings.Split(string(content), ",") 379 // if len(cs) != 3 { 380 // return STOP, 0, 0 381 // } 382 // status, err := strconv.Atoi(cs[0]) 383 // if err != nil { 384 // return STOP, 0, 0 385 // } 386 // if status < STOP || status > RUNNING { 387 // return STOP, 0, 0 388 // } 389 // pid, err := strconv.Atoi(cs[1]) 390 // if err != nil { 391 // return STOP, 0, 0 392 // } 393 394 // _, err = os.FindProcess(pid) 395 // if err != nil { 396 // return STOP, 0, 0 397 // } 398 399 // port, err := strconv.Atoi(cs[2]) 400 // if err != nil { 401 // return STOP, 0, 0 402 // } 403 404 // return status, pid, port 405 // } 406 407 // func getPidPath() (string, error) { 408 // homeDir, err := com.HomeDir() 409 // if err != nil { 410 // return "", err 411 // } 412 413 // pFile := strings.Replace("~/.gopm/var/", "~", homeDir, -1) 414 // os.MkdirAll(pFile, os.ModePerm) 415 // return pFile + "pid", nil 416 // } 417 418 // func startService(listen, port string) error { 419 // homeDir, err := com.HomeDir() 420 // if err != nil { 421 // return err 422 // } 423 424 // pFile, err := getPidPath() 425 // if err != nil { 426 // return err 427 // } 428 429 // f, err := os.OpenFile(pFile, os.O_RDWR|os.O_CREATE, 0700) 430 // if err != nil { 431 // return err 432 // } 433 // defer f.Close() 434 // _, err = f.WriteString(fmt.Sprintf("%v,%v,%v", RUNNING, os.Getpid(), port)) 435 // if err != nil { 436 // return err 437 // } 438 439 // dbDir = strings.Replace(dbDir, "~", homeDir, -1) 440 441 // db, err = leveldb.OpenFile(dbDir, nil) 442 // if err != nil { 443 // return err 444 // } 445 // defer db.Close() 446 447 // // these handlers should only access by localhost 448 // http.HandleFunc("/add", addHandler) 449 // http.HandleFunc("/rm", rmHandler) 450 451 // // these handlers can be accessed according listen's ip 452 // http.HandleFunc("/search", searchHandler) 453 // http.HandleFunc("/searche", searcheHandler) 454 // http.ListenAndServe(listen+":"+port, nil) 455 // return nil 456 // } 457 458 // func searchHandler(w http.ResponseWriter, r *http.Request) { 459 // r.ParseForm() 460 // ids := make(map[string]bool) 461 // for key, _ := range r.Form { 462 // iter := db.NewIterator(ro) 463 // rkey := fmt.Sprintf("key:%v:", strings.ToLower(key)) 464 // if iter.Seek([]byte(rkey)) { 465 // k := iter.Key() 466 // if !strings.HasPrefix(string(k), rkey) { 467 // break 468 // } else { 469 // ids[string(k)] = true 470 // } 471 // } 472 // for iter.Next() { 473 // k := iter.Key() 474 // if !strings.HasPrefix(string(k), rkey) { 475 // break 476 // } 477 // ids[string(k)] = true 478 // } 479 // } 480 481 // pkgs := make([]string, 0) 482 483 // for id, _ := range ids { 484 // idkeys := strings.SplitN(id, ":", -1) 485 // rId := idkeys[len(idkeys)-1] 486 // //fmt.Println(rId) 487 // pkg, err := dbGet(fmt.Sprintf("pkg:%v", rId)) 488 // if err != nil { 489 // com.ColorLog(err.Error()) 490 // continue 491 // } 492 // desc, err := dbGet(fmt.Sprintf("desc:%v", rId)) 493 // if err != nil { 494 // com.ColorLog(err.Error()) 495 // continue 496 // } 497 // pkgs = append(pkgs, fmt.Sprintf(`{"pkg":"%v", "desc":"%v"}`, pkg, desc)) 498 // } 499 500 // w.Write([]byte("[" + strings.Join(pkgs, ", ") + "]")) 501 // } 502 503 // func searcheHandler(w http.ResponseWriter, r *http.Request) { 504 // //if r.Method == "POST" { 505 // r.ParseForm() 506 // pkgs := make([]string, 0) 507 // for key, _ := range r.Form { 508 // rId, err := dbGet("index:" + key) 509 // if err != nil { 510 // com.ColorLog(err.Error()) 511 // continue 512 // } 513 514 // desc, err := dbGet(fmt.Sprintf("desc:%v", rId)) 515 // if err != nil { 516 // com.ColorLog(err.Error()) 517 // continue 518 // } 519 520 // pkgs = append(pkgs, fmt.Sprintf(`{"pkg":"%v", "desc":"%v"}`, key, desc)) 521 // } 522 523 // w.Write([]byte("[" + strings.Join(pkgs, ", ") + "]")) 524 // //} 525 // } 526 527 // func addHandler(w http.ResponseWriter, r *http.Request) { 528 // //if r.Method == "POST" { 529 // r.ParseForm() 530 531 // nod := new(doc.Node) 532 // nod.ImportPath = r.FormValue("importPath") 533 // nod.Synopsis = r.FormValue("synopsis") 534 // nod.DownloadURL = r.FormValue("downloadURL") 535 // isGetDeps, err := strconv.ParseBool(r.FormValue("isGetDeps")) 536 // if err != nil { 537 // com.ColorLog("[ERRO] SEVER: Cannot get deps") 538 // } 539 // nod.IsGetDeps = isGetDeps 540 // nod.Type = r.FormValue("type") 541 // nod.Value = r.FormValue("value") 542 543 // err = addNode(nod) 544 // if err != nil { 545 // com.ColorLog("[ERRO] SEVER: Cannot add node[ %s ]\n", err) 546 // } 547 // //} 548 // } 549 550 // func rmHandler(w http.ResponseWriter, r *http.Request) { 551 552 // }