func Download(ctx *middleware.Context) { importPath := archive.GetRootPath(ctx.Query("pkgname")) rev := ctx.Query("revision") r, err := models.CheckPkg(importPath, rev) if err != nil { ctx.JSON(422, map[string]interface{}{ "error": err.Error(), }) return } if err = models.IncreasePackageDownloadCount(importPath); err != nil { ctx.JSON(500, map[string]interface{}{ "error": err.Error(), }) return } else if err = models.AddDownloader(ctx.RemoteAddr()); err != nil { ctx.JSON(500, map[string]interface{}{ "error": err.Error(), }) return } ext := archive.GetExtension(importPath) serveName := path.Base(importPath) + "-" + base.ShortSha(r.Revision) + ext switch r.Storage { case models.LOCAL: ctx.ServeFile(path.Join(setting.ArchivePath, importPath, r.Revision+ext), serveName) case models.QINIU: ctx.Redirect("http://" + setting.BucketUrl + "/" + importPath + "-" + r.Revision + ext) } }
// KeyName returns QiNiu key name. func (r *Revision) KeyName() (string, error) { if r.Storage == LOCAL { return "", ErrRevisionIsLocal } if err := r.GetPackage(); err != nil { return "", err } return r.Pkg.ImportPath + "-" + r.Revision + archive.GetExtension(r.Pkg.ImportPath), nil }
// BlockPackage blocks given package. func BlockPackage(importPath, note string) (keys []string, err error) { pkg, err := GetPakcageByPath(importPath) if err != nil { return nil, err } has, err := x.Where("import_path=?", pkg.ImportPath).Get(new(Block)) if err != nil { return nil, err } else if has { return nil, nil } sess := x.NewSession() defer sess.Close() if err = sess.Begin(); err != nil { return nil, err } keys = make([]string, 0, 10) revs, err := pkg.GetRevisions() if err != nil { return nil, fmt.Errorf("error getting revisions(%s): %v", pkg.ImportPath, err) } ext := archive.GetExtension(pkg.ImportPath) for _, rev := range revs { switch rev.Storage { case QINIU: keys = append(keys, pkg.ImportPath+"-"+rev.Revision+ext) } if _, err = sess.Id(rev.Id).Delete(new(Revision)); err != nil { sess.Rollback() return nil, err } } os.RemoveAll(path.Join(setting.ArchivePath, pkg.ImportPath)) if _, err = sess.Id(pkg.Id).Delete(new(Package)); err != nil { sess.Rollback() return nil, err } b := &Block{ ImportPath: pkg.ImportPath, Note: note, } if _, err = sess.Insert(b); err != nil { sess.Rollback() return nil, err } return keys, sess.Commit() }
// RunBlockRule applies given block rule to all packages. func RunBlockRule(id int64) (count int64, keys []string, err error) { r, err := GetBlockRuleById(id) if err != nil { return 0, nil, err } exp, err := regexp.Compile(r.Rule) if err != nil { return 0, nil, err } keys = make([]string, 0, 10) err = x.Iterate(new(Package), func(idx int, bean interface{}) error { pkg := bean.(*Package) if !exp.MatchString(pkg.ImportPath) { return nil } revs, err := pkg.GetRevisions() if err != nil { return fmt.Errorf("error getting revisions(%s): %v", pkg.ImportPath, err) } // Delete package archives. ext := archive.GetExtension(pkg.ImportPath) for _, rev := range revs { switch rev.Storage { case QINIU: keys = append(keys, pkg.ImportPath+"-"+rev.Revision+ext) } if _, err = x.Id(rev.Id).Delete(new(Revision)); err != nil { return fmt.Errorf("error deleting revision(%s-%s): %v", pkg.ImportPath, rev.Revision, err) } } os.RemoveAll(path.Join(setting.ArchivePath, pkg.ImportPath)) if setting.ProdMode { if _, err = x.Id(pkg.Id).Delete(new(Package)); err != nil { return fmt.Errorf("error deleting package(%s): %v", pkg.ImportPath, err) } } log.Info("[%d] Package blocked: %s", r.Id, pkg.ImportPath) count++ return nil }) return count, keys, err }
func BlockPackage(ctx *middleware.Context) { id := ctx.QueryInt64("id") pkg, err := models.GetPakcageById(id) if err != nil { if err == models.ErrPackageNotExist { ctx.JSON(404, map[string]string{ "error": err.Error(), }) } else { ctx.JSON(500, map[string]string{ "error": fmt.Sprintf("fail to get package by ID(%d): %v", id, err), }) } return } revs, err := pkg.GetRevisions() if err != nil { ctx.JSON(500, map[string]string{ "error": fmt.Sprintf("fail to get package revisions by ID(%d): %v", id, err), }) return } // Delete package archives. ext := archive.GetExtension(pkg.ImportPath) for _, rev := range revs { switch rev.Storage { case models.QINIU: key := pkg.ImportPath + "-" + rev.Revision + ext if err = qiniu.DeleteArchive(key); err != nil { ctx.JSON(500, map[string]string{ "error": fmt.Sprintf("fail to delete archive(%s): %v", key, err), }) return } } } os.RemoveAll(path.Join(setting.ArchivePath, pkg.ImportPath)) if err = models.BlockPackage(pkg, revs, ctx.Query("note")); err != nil { ctx.JSON(500, map[string]string{ "error": fmt.Sprintf("fail to block package by ID(%d): %v", id, err), }) return } ctx.JSON(200, map[string]interface{}{ "ok": true, }) }
func Download(ctx *middleware.Context) { ctx.Data["Title"] = ctx.Tr("download") ctx.Data["PageIsDownload"] = true importPath := archive.GetRootPath(ctx.Query("pkgname")) if ctx.Req.Method == "POST" { rev := ctx.Query("revision") r, err := models.CheckPkg(importPath, rev) if err != nil { ctx.Data["pkgname"] = importPath ctx.Data["revision"] = rev errMsg := err.Error() if err == archive.ErrNotMatchAnyService { ctx.Data["Err_PkgName"] = true errMsg = ctx.Tr("download.err_not_match_service") } else if _, ok := err.(*models.BlockError); ok { errMsg = ctx.Tr("download.err_package_blocked", err.Error()) } ctx.RenderWithErr(errMsg, "download", nil) return } if err = models.IncreasePackageDownloadCount(importPath); err != nil { ctx.Handle(500, "IncreasePackageDownloadCount", err) return } else if err = models.AddDownloader(ctx.RemoteAddr()); err != nil { ctx.Handle(500, "AddDownloader", err) return } ext := archive.GetExtension(importPath) serveName := path.Base(importPath) + "-" + base.ShortSha(r.Revision) + ext switch r.Storage { case models.LOCAL: ctx.ServeFile(path.Join(setting.ArchivePath, importPath, r.Revision+ext), serveName) case models.QINIU: ctx.Redirect("http://" + setting.BucketUrl + "/" + importPath + "-" + r.Revision + ext) } return } ctx.Data["pkgname"] = importPath ctx.HTML(200, "download") }
func cleanExpireRevesions() { if err := x.Where("updated<?", time.Now().Add(_EXPIRE_DURATION)). Iterate(new(Revision), func(idx int, bean interface{}) (err error) { rev := bean.(*Revision) if err = rev.GetPackage(); err != nil { return err } if _, err = x.Id(rev.Id).Delete(new(Revision)); err != nil { return err } ext := archive.GetExtension(rev.Pkg.ImportPath) fpath := path.Join(setting.ArchivePath, rev.Pkg.ImportPath, rev.Revision+ext) switch rev.Storage { case LOCAL: os.Remove(fpath) log.Info("Revision deleted: %s", fpath) return nil case QINIU: key, err := rev.KeyName() if err != nil { return err } if setting.ProdMode { if err = qiniu.DeleteArchive(key); err != nil { return err } } log.Info("Revision deleted: %s", key) return nil default: return nil } return nil }); err != nil { log.Error(3, "Fail to clean expire revisions: %v", err) } }
// uploadArchives checks and uploads local archives to QiNiu. func uploadArchives() { revs, err := GetLocalRevisions() if err != nil { log.Error(4, "Fail to get local revisions: %v", err) return } // Upload. for _, rev := range revs { pkg, err := GetPakcageById(rev.PkgId) if err != nil { log.Error(4, "Fail to get package by ID(%d): %v", rev.PkgId, err) continue } ext := archive.GetExtension(pkg.ImportPath) key := pkg.ImportPath + "-" + rev.Revision + ext localPath := path.Join(pkg.ImportPath, rev.Revision) fpath := path.Join(setting.ArchivePath, localPath+ext) // Move. // rsCli := rs.New(nil) // log.Info(key) // err = rsCli.Move(nil, setting.BucketName, pkg.ImportPath+"-"+rev.Revision, setting.BucketName, key) // if err != nil { // log.Error(4, rev.Revision) // } // continue if !com.IsFile(fpath) { log.Debug("Delete: %v", fpath) DeleteRevisionById(rev.Id) continue } // Check archive size. f, err := os.Open(fpath) if err != nil { log.Error(4, "Fail to open file(%s): %v", fpath, err) continue } fi, err := f.Stat() if err != nil { log.Error(4, "Fail to get file info(%s): %v", fpath, err) continue } // Greater then MAX_UPLOAD_SIZE. if fi.Size() > setting.MaxUploadSize<<20 { log.Debug("Ignore large archive: %v", fpath) continue } log.Debug("Uploading: %s", localPath) if err = qiniu.UploadArchive(key, fpath); err != nil { log.Error(4, "Fail to upload file(%s): %v", fpath, err) continue } rev.Storage = QINIU if err := UpdateRevision(rev); err != nil { log.Error(4, "Fail to upadte revision(%d): %v", rev.Id, err) continue } os.Remove(fpath) log.Info("Uploaded: %s", localPath) } }
func ListLargeRevisions(ctx *middleware.Context) { revs, err := models.GetLocalRevisions() if err != nil { ctx.JSON(500, map[string]string{ "error": fmt.Sprintf("fail to get local revisions: %v", err), }) return } largeRevs := make([]*ApiRevesion, 0, len(revs)/2) for _, rev := range revs { pkg, err := models.GetPakcageById(rev.PkgId) if err != nil { ctx.JSON(500, map[string]string{ "error": fmt.Sprintf("fail to get package by ID(%d): %v", rev.PkgId, err), }) return } ext := archive.GetExtension(pkg.ImportPath) localPath := path.Join(pkg.ImportPath, rev.Revision) fpath := path.Join(setting.ArchivePath, localPath+ext) if !com.IsFile(fpath) { continue } // Check archive size. f, err := os.Open(fpath) if err != nil { ctx.JSON(500, map[string]string{ "error": fmt.Sprintf("fail to open file(%s): %v", fpath, err), }) return } fi, err := f.Stat() if err != nil { ctx.JSON(500, map[string]string{ "error": fmt.Sprintf("fail to get file info(%s): %v", fpath, err), }) return } // Greater then MAX_UPLOAD_SIZE. if fi.Size() > setting.MaxUploadSize<<20 { largeRevs = append(largeRevs, &ApiRevesion{ Id: rev.Id, Package: &ApiPackage{ Id: pkg.Id, ImportPath: pkg.ImportPath, Created: pkg.Created, }, Revision: rev.Revision, Size: fi.Size(), Updated: rev.Updated, }) continue } } ctx.JSON(200, map[string]interface{}{ "revisions": &largeRevs, }) }