Пример #1
0
// DeleteProject deletes everything about the path in database, and update import information.
func DeleteProject(path string) error {
	// Check path length to reduce connect times. (except launchpad.net)
	if path[0] != 'l' && len(strings.Split(path, "/")) <= 2 {
		return errors.New("models.DeleteProject(): Short path as not needed.")
	}

	// Connect to database.
	q := connDb()
	defer q.Db.Close()

	var i1, i2, i3 int64
	// Delete package information.
	info := new(PkgInfo)
	err := q.WhereEqual("path", path).Find(info)
	if err == nil {
		i1, err = q.Delete(info)
		if err != nil {
			beego.Error("models.DeleteProject(): Information:", err)
		}
	}

	// Delete package declaration
	pdecl := new(PkgDecl)
	err = q.WhereEqual("path", path).Find(pdecl)
	if err == nil {
		i2, err = q.Delete(pdecl)
		if err != nil {
			beego.Error("models.DeleteProject(): Declaration:", err)
		} else if info.Id > 0 && !utils.IsGoRepoPath(path) {
			// Don't need to check standard library.
			// Update import information.
			imports := strings.Split(pdecl.Imports, "|")
			imports = imports[:len(imports)-1]
			for _, v := range imports {
				if !utils.IsGoRepoPath(v) {
					// Only count non-standard library.
					updateImportInfo(q, v, int(info.Id), false)
				}
			}
		}
	}

	// Delete package documentation
	pdoc := &PkgDoc{Path: path}
	i3, err = q.Delete(pdoc)
	if err != nil {
		beego.Error("models.DeleteProject(): Documentation:", err)
	}

	if i1+i2+i3 > 0 {
		beego.Info("models.DeleteProject(", path, i1, i2, i3, ")")
	}

	return nil
}
Пример #2
0
// checkSpecialUsage checks special usage of keywords.
// It returns true if it is a special usage, false otherwise.
func checkSpecialUsage(this *SearchRouter, q string) bool {
	switch {
	case q == "gorepo": // Show list of standard library.
		pinfos, _ := models.GetGoRepo()
		if len(pinfos) > 0 {
			this.Data["IsFindPro"] = true
			this.Data["Results"] = pinfos
		}
		return true
	case q == "imports": // Show imports package list.
		pkgs := strings.Split(this.Input().Get("pkgs"), "|")
		pinfos, _ := models.GetGroupPkgInfo(pkgs)
		if len(pinfos) > 0 {
			this.Data["IsFindPro"] = true
			this.Data["Results"] = pinfos
		}
		return true
	case q == "imported": // Show packages that import this project.
		pkgs := strings.Split(
			strings.Replace(this.Input().Get("pkgs"), "$", "", -1), "|")
		pinfos := models.GetGroupPkgInfoById(pkgs)
		if len(pinfos) > 0 {
			this.Data["IsFindPro"] = true
			this.Data["Results"] = pinfos
		}
		return true
	case strings.Index(q, ":l=") > -1: // Add label to the project.
		// Get label(s).
		i := strings.Index(q, ":l=")
		if utils.IsGoRepoPath(q[:i]) {
			this.Redirect("/"+q[:i], 302)
			return true
		}

		if isLabel(q[i+3:]) && models.UpdateLabelInfo(q[:i], q[i+3:], true) {
			this.Redirect("/"+q[:i], 302)
		}
		return true
	case strings.Index(q, ":rl=") > -1: // Remove label to the project.
		// Get label(s).
		i := strings.Index(q, ":rl=")
		if utils.IsGoRepoPath(q[:i]) {
			this.Redirect("/"+q[:i], 302)
			return true
		}

		if isLabel(q[i+4:]) && models.UpdateLabelInfo(q[:i], q[i+4:], false) {
			this.Redirect("/"+q[:i], 302)
		}
		return true
	}

	return false
}
Пример #3
0
// checkSpecialUsage checks special usage of keywords.
// It returns true if it is a special usage, false otherwise.
func checkSpecialUsage(this *SearchController, q string) bool {
	switch {
	case q == "gorepo": // Show list of standard library.
		pkgInfos, _ := models.GetGoRepo()
		// Show results after searched.
		if len(pkgInfos) > 0 {
			this.Data["IsFindPro"] = true
			this.Data["AllPros"] = pkgInfos
		}
		return true
	case q == "imports": // Show imports package list.
		pkgs := strings.Split(this.Input().Get("pkgs"), "|")
		pinfos, _ := models.GetGroupPkgInfo(pkgs)
		if len(pinfos) > 0 {
			this.Data["IsFindPro"] = true
			this.Data["AllPros"] = pinfos
		}
		return true
	case q == "imported": // Show packages that import this project.
		pkgs := strings.Split(this.Input().Get("pkgs"), "|")
		pinfos, _ := models.GetGroupPkgInfoById(pkgs)
		if len(pinfos) > 0 {
			this.Data["IsFindPro"] = true
			this.Data["AllPros"] = pinfos
		}
		return true
	case strings.Index(q, ":tag=") > -1: // Add tag(s) to the project.
		// Get tag(s).
		i := strings.Index(q, ":tag=")
		if utils.IsGoRepoPath(q[:i]) {
			this.Redirect("/"+q[:i], 302)
			return true
		}

		if isTag(q[i+5:]) && models.UpdateTagInfo(q[:i], q[i+5:], true) {
			this.Redirect("/"+q[:i], 302)
		}
		return true
	case strings.Index(q, ":rtag=") > -1: // Remove tag(s) to the project.
		// Get tag(s).
		i := strings.Index(q, ":rtag=")
		if utils.IsGoRepoPath(q[:i]) {
			this.Redirect("/"+q[:i], 302)
			return true
		}

		if isTag(q[i+6:]) && models.UpdateTagInfo(q[:i], q[i+6:], false) {
			this.Redirect("/"+q[:i], 302)
		}
		return true
	}

	return false
}
Пример #4
0
// SaveProject save package information, declaration, documentation to database, and update import information.
func SaveProject(pinfo *PkgInfo, pdecl *PkgDecl, pdoc *PkgDoc, imports []string) error {
	// Connect to database.
	q := connDb()
	defer q.Close()

	// Save package information.
	info := new(PkgInfo)
	err := q.WhereEqual("path", pinfo.Path).Find(info)
	if err == nil {
		pinfo.Id = info.Id
	}

	_, err = q.Save(pinfo)
	if err != nil {
		beego.Error("models.SaveProject -> Information:", err)
	}

	// Save package declaration
	if pdecl != nil {
		decl := new(PkgDecl)
		cond := qbs.NewCondition("path = ?", pinfo.Path).And("tag = ?", pdecl.Tag)
		err = q.Condition(cond).Find(decl)
		if err == nil {
			pdecl.Id = decl.Id
		}

		_, err = q.Save(pdecl)
		if err != nil {
			beego.Error("models.SaveProject -> Declaration:", err)
		}
	}

	// Save package documentation
	if pdoc != nil && len(pdoc.Doc) > 0 {
		_, err = q.Save(pdoc)
		if err != nil {
			beego.Error("models.SaveProject -> Documentation:", err)
		}
	}

	// Don't need to check standard library.
	if imports != nil && !utils.IsGoRepoPath(pinfo.Path) {
		// Update import information.
		for _, v := range imports {
			if !utils.IsGoRepoPath(v) {
				// Only count non-standard library.
				updateImportInfo(q, v, int(pinfo.Id), true)
			}
		}
	}
	return nil
}
Пример #5
0
// getRepo downloads package data.
func getRepo(client *http.Client, importPath string, etag string) (pdoc *Package, err error) {
	const VER_PREFIX = PACKAGE_VER + "-"

	// Check version prefix.
	if strings.HasPrefix(etag, VER_PREFIX) {
		etag = etag[len(VER_PREFIX):]
	} else {
		etag = ""
	}

	switch {
	case utils.IsGoRepoPath(importPath):
		pdoc, err = getStandardDoc(client, importPath, etag)
	case utils.IsValidRemotePath(importPath):
		pdoc, err = getStatic(client, importPath)
		if err == errNoMatch {
			pdoc, err = getDynamic(client, importPath)
		}
	default:
		return nil, errors.New("doc.getRepo(): No match: " + importPath)
	}

	// Save revision tag.
	if pdoc != nil {
		pdoc.Etag = VER_PREFIX + pdoc.Etag
	}

	return pdoc, err
}
Пример #6
0
// getRepo downloads package data and returns 'Package' by given import path and tag.
// It returns error when error occurs in the underlying functions.
func getRepo(client *http.Client, path, tag, ptag string) (pdoc *hv.Package, err error) {
	switch {
	case utils.IsGoRepoPath(path):
		pdoc, err = getStandardDoc(client, path, tag, ptag)
	case utils.IsValidRemotePath(path):
		pdoc, err = getStatic(client, path, tag, ptag)
		if err == errNoMatch {
			pdoc, err = getDynamic(client, path, tag, ptag)
		}
	default:
		return nil, errors.New(
			fmt.Sprintf("doc.getRepo -> No match( %s:%s )", path, tag))
	}

	if pdoc == nil {
		return nil, err
	}

	pdoc.PkgVer = hv.PACKAGE_VER

	// Render README.
	for name, content := range pdoc.Readme {
		p, err := httplib.Post("https://api.github.com/markdown/raw?"+GetGithubCredentials()).
			Header("Content-Type", "text/plain").Body(content).Bytes()
		if err != nil {
			return nil, errors.New(
				fmt.Sprintf("doc.getRepo -> Render README( %s:%s ): %v", path, tag, err))
		}
		pdoc.Readme[name] = p
	}
	return pdoc, err
}
Пример #7
0
// crawlDoc fetchs package from VCS.
func crawlDoc(path string, etag string, views int64) (pdoc *Package, err error) {
	// I have no idea what the f**k does this mean.
	if i := strings.Index(path, "/libgo/go/"); i > 0 && utils.IsGoRepoPath(path[i+len("/libgo/go/"):]) {
		// Go Frontend source tree mirror.
		pdoc = nil
		err = errors.New("Go Frontend source tree mirror.")
	} else {
		var pdocNew *Package
		pdocNew, err = getRepo(httpClient, path, etag)

		// For timeout logic in client.go to work, we cannot leave connections idling. This is ugly.
		httpTransport.CloseIdleConnections()

		if err != errNotModified && pdocNew != nil {
			pdoc = pdocNew
			pdoc.Views = views
		}
	}

	switch {
	case err == nil:
		pdoc.Views = views
		if err = SaveProject(pdoc); err != nil {
			beego.Error("doc.SaveProject(", path, "):", err)
		}
	case isNotFound(err):
		// We do not need to delete standard library, so here is fine.
		if err = models.DeleteProject(path); err != nil {
			beego.Error("doc.DeleteProject(", path, "):", err)
		}
	}
	return pdoc, err
}
Пример #8
0
func getPkgInfoWithQ(path, tag string, q *qbs.Qbs) (*hv.PkgInfo, error) {
	// Check path length to reduce connect times.
	if len(path) == 0 {
		return nil, errors.New("models.getPkgInfoWithQ -> Empty path as not found.")
	}

	pinfo := new(hv.PkgInfo)
	q.WhereEqual("import_path", path).Find(pinfo)

	proPath := utils.GetProjectPath(path)
	if utils.IsGoRepoPath(path) {
		proPath = "code.google.com/p/go"
	}
	beego.Trace("models.getPkgInfoWithQ -> proPath:", proPath)
	ptag := new(PkgTag)
	cond := qbs.NewCondition("path = ?", proPath).And("tag = ?", tag)
	err := q.Condition(cond).Find(ptag)
	if err != nil {
		pinfo.Ptag = "ptag"
		return pinfo, errors.New(
			fmt.Sprintf("models.getPkgInfoWithQ( %s:%s ) -> 'PkgTag': %s", path, tag, err))
	}
	pinfo.Vcs = ptag.Vcs
	pinfo.Tags = ptag.Tags

	// Only 'PkgInfo' cannot prove that package exists,
	// we have to check 'PkgDecl' as well in case it was deleted by mistake.

	pdecl := new(PkgDecl)
	cond = qbs.NewCondition("pid = ?", pinfo.Id).And("tag = ?", tag)
	err = q.Condition(cond).Find(pdecl)
	if err != nil {
		// Basically, error means not found, so we set 'pinfo.PkgVer' to 0
		// because server uses it to decide whether force update.
		pinfo.PkgVer = 0
		pinfo.Ptag = "ptag"
		return pinfo, errors.New(
			fmt.Sprintf("models.getPkgInfoWithQ( %s:%s ) -> 'PkgDecl': %s", path, tag, err))
	}

	docPath := path + utils.TagSuffix("-", tag)
	if !com.IsExist("." + utils.DocsJsPath + docPath + ".js") {
		pinfo.PkgVer = 0
		pinfo.Ptag = "ptag"
		return pinfo, errors.New(
			fmt.Sprintf("models.getPkgInfoWithQ( %s:%s ) -> JS: File not found", path, tag))
	}

	return pinfo, nil
}
Пример #9
0
// SaveProject save package information, declaration, documentation to database, and update import information.
func SaveProject(pinfo *PkgInfo, pdecl *PkgDecl, pdoc *PkgDoc, imports []string) error {
	// Connect to database.
	q, err := connDb()
	if err != nil {
		beego.Error("models.SaveProject():", err)
	}
	defer q.Db.Close()

	// Save package information.
	info := new(PkgInfo)
	err = q.WhereEqual("path", pinfo.Path).Find(info)
	if err != nil {
		_, err = q.Save(pinfo)
	} else {
		pinfo.Id = info.Id
		_, err = q.Save(pinfo)
	}
	if err != nil {
		beego.Error("models.SaveProject(): Information:", err)
	}

	// Save package declaration
	_, err = q.Save(pdecl)
	if err != nil {
		beego.Error("models.SaveProject(): Declaration:", err)
	}

	// Save package documentation
	if len(pdoc.Doc) > 0 {
		_, err = q.Save(pdoc)
		if err != nil {
			beego.Error("models.SaveProject(): Documentation:", err)
		}
	}

	// Update import information.
	for _, v := range imports {
		if !utils.IsGoRepoPath(v) {
			// Only count non-standard library.
			updateImportInfo(q, v, int(pinfo.Id), true)
		}
	}
	return nil
}
Пример #10
0
// getRepo downloads package data and returns 'Package' by given import path and tag.
// It returns error when error occurs in the underlying functions.
func getRepo(client *http.Client, path, tag, ptag string) (pdoc *hv.Package, err error) {
	switch {
	case utils.IsGoRepoPath(path):
		pdoc, err = getStandardDoc(client, path, tag, ptag)
	case utils.IsValidRemotePath(path):
		pdoc, err = getStatic(client, path, tag, ptag)
		if err == errNoMatch {
			pdoc, err = getDynamic(client, path, tag, ptag)
		}
	default:
		return nil, errors.New(
			fmt.Sprintf("doc.getRepo -> No match( %s:%s )", path, tag))
	}

	if pdoc != nil {
		pdoc.PkgVer = hv.PACKAGE_VER
	}

	return pdoc, err
}
Пример #11
0
// Get implemented Get method for HomeRouter.
func (this *HomeRouter) Get() {
	// Filter unusual User-Agent.
	ua := this.Ctx.Request.Header.Get("User-Agent")
	if len(ua) < 20 {
		beego.Warn("User-Agent:", this.Ctx.Request.Header.Get("User-Agent"))
		this.Ctx.WriteString("")
		return
	}

	// Set language version.
	curLang := globalSetting(this.Ctx, this.Input(), this.Data)

	// Get argument(s).
	q := strings.TrimRight(
		strings.TrimSpace(this.Input().Get("q")), "/")

	if path, ok := utils.IsBrowseURL(q); ok {
		q = path
	}

	// Get pure URL.
	reqUrl := this.Ctx.Request.RequestURI[1:]
	if i := strings.Index(reqUrl, "?"); i > -1 {
		reqUrl = reqUrl[:i]
		if path, ok := utils.IsBrowseURL(reqUrl); ok {
			reqUrl = path
		}
	}

	// Redirect to query string.
	if len(reqUrl) == 0 && len(q) > 0 {
		reqUrl = q
		this.Redirect("/"+reqUrl, 302)
		return
	}

	// User Recent projects.
	urpids, _ := this.Ctx.Request.Cookie("UserRecentPros")
	urpts, _ := this.Ctx.Request.Cookie("URPTimestamps")

	this.TplNames = "home_" + curLang.Lang + ".html"
	// Check to show home page or documentation page.
	if len(reqUrl) == 0 && len(q) == 0 {
		serveHome(this, urpids, urpts)
	} else {
		// Documentation.
		this.TplNames = "docs_" + curLang.Lang + ".html"
		broPath := reqUrl // Browse path.

		// Check if it's the standard library.
		if utils.IsGoRepoPath(broPath) {
			broPath = "code.google.com/p/go/source/browse/src/pkg/" + broPath
		}

		// Check if it's a remote path that can be used for 'go get', if not means it's a keyword.
		if !utils.IsValidRemotePath(broPath) {
			// Search.
			this.Redirect("/search?q="+reqUrl, 302)
			return
		}

		// Get tag field.
		tag := strings.TrimSpace(this.Input().Get("tag"))
		if tag == "master" || tag == "default" {
			tag = ""
		}

		// Check documentation of this import path, and update automatically as needed.
		pdoc, err := doc.CheckDoc(reqUrl, tag, doc.HUMAN_REQUEST)
		if err == nil {
			if pdoc != nil {
				pdoc.UserExamples = getUserExamples(pdoc.ImportPath)
				// Generate documentation page.
				if generatePage(this, pdoc, broPath, tag, curLang.Lang) {
					ps, ts := updateCacheInfo(pdoc, urpids, urpts)
					this.Ctx.SetCookie("UserRecentPros", ps, 9999999999, "/")
					this.Ctx.SetCookie("URPTimestamps", ts, 9999999999, "/")
					return
				}
			}
		} else {
			this.Data["IsHasError"] = true
			this.Data["ErrMsg"] = strings.Replace(err.Error(),
				doc.GetGithubCredentials(), "<githubCred>", 1)
			beego.Error("HomeRouter.Get ->", err)
			this.TplNames = "home_" + curLang.Lang + ".html"
			serveHome(this, urpids, urpts)
			return
		}

		this.Redirect("/search?q="+reqUrl, 302)
		return
	}
}
Пример #12
0
// generatePage genarates documentation page for project.
// it returns false when its a invaild(empty) project.
func generatePage(this *HomeController, pdoc *doc.Package, q string, lang string) bool {
	// Set properties.
	this.TplNames = "docs_" + lang + ".html"

	// Refresh (within 10 seconds).
	this.Data["IsRefresh"] = pdoc.Created.Add(10 * time.Second).UTC().After(time.Now().UTC())

	// Get project name.
	lastIndex := strings.LastIndex(q, "/")
	proName := q[lastIndex+1:]
	if i := strings.Index(proName, "?"); i > -1 {
		proName = proName[:i]
	}
	this.Data["ProName"] = proName

	// Project VCS home page.
	switch {
	case q[:4] == "code": // code.google.com
		if strings.Index(q, "source/") == -1 {
			this.Data["ProPath"] = strings.Replace(q, pdoc.ProjectName, pdoc.ProjectName+"/source/browse", 1)
		} else {
			this.Data["ProPath"] = q
		}
	case q[:3] == "git": // github.com
		if proName != pdoc.ProjectName {
			// Not root.
			this.Data["ProPath"] = strings.Replace(q, proName, "tree/master/"+proName, 1)
		} else {
			this.Data["ProPath"] = q + "/tree/master"
		}
	}

	this.Data["Views"] = pdoc.Views + 1

	// Remove last "/".
	if urlLen := len(q); q[urlLen-1] == '/' {
		q = q[:urlLen-1]
	}

	if utils.IsGoRepoPath(pdoc.ImportPath) {
		this.Data["IsGoRepo"] = true
	}
	pkgDocPath := q[:lastIndex]
	this.Data["ProDocPath"] = pkgDocPath // Upper level project URL.

	// Introduction.
	this.Data["ImportPath"] = pdoc.ImportPath
	// Load project data from database.
	pdecl, err := models.LoadProject(pdoc.ImportPath)
	if err != nil {
		beego.Error("SearchController.generatePage(): models.LoadProject()", err)
		return false
	}
	var buf bytes.Buffer
	godoc.ToHTML(&buf, pdecl.Doc, nil)
	pkgInfo := buf.String()
	pkgInfo = strings.Replace(pkgInfo, "<p>", "<p><b>", 1)
	pkgInfo = strings.Replace(pkgInfo, "</p>", "</b></p>", 1)
	this.Data["PkgFullIntro"] = pkgInfo
	// Convert data format.
	err = ConvertDataFormat(pdoc, pdecl)
	if err != nil {
		beego.Error("SearchController.generatePage(): ConvertDataFormat", err)
		return false
	}

	links := make([]*utils.Link, 0, len(pdoc.Types)+len(pdoc.Imports))
	// Get all types and import packages
	for _, t := range pdoc.Types {
		links = append(links, &utils.Link{
			Name:    t.Name,
			Comment: t.Doc,
		})
	}
	for _, v := range pdoc.Imports {
		links = append(links, &utils.Link{
			Name: path.Base(v) + ".",
			Path: v,
		})
	}

	// Index.
	this.Data["IsHasConst"] = len(pdoc.Consts) > 0
	this.Data["IsHasVar"] = len(pdoc.Vars) > 0
	this.Data["Funcs"] = pdoc.Funcs
	for i, f := range pdoc.Funcs {
		buf.Reset()
		godoc.ToHTML(&buf, f.Doc, nil)
		f.Doc = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, f.Decl, links)
		f.FmtDecl = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, f.Code, links)
		f.Code = buf.String()
		pdoc.Funcs[i] = f
	}
	this.Data["Types"] = pdoc.Types
	for i, t := range pdoc.Types {
		for j, f := range t.Funcs {
			buf.Reset()
			godoc.ToHTML(&buf, f.Doc, nil)
			f.Doc = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, f.Decl, links)
			f.FmtDecl = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, f.Code, links)
			f.Code = buf.String()
			t.Funcs[j] = f
		}
		for j, m := range t.Methods {
			buf.Reset()
			godoc.ToHTML(&buf, m.Doc, nil)
			m.Doc = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, m.Decl, links)
			m.FmtDecl = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, m.Code, links)
			m.Code = buf.String()
			t.Methods[j] = m
		}
		buf.Reset()
		godoc.ToHTML(&buf, t.Doc, nil)
		t.Doc = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, t.Decl, links)
		t.FmtDecl = buf.String()
		pdoc.Types[i] = t
	}

	// Constants.
	this.Data["Consts"] = pdoc.Consts
	for i, v := range pdoc.Consts {
		buf.Reset()
		utils.FormatCode(&buf, v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Consts[i] = v
	}

	// Variables.
	this.Data["Vars"] = pdoc.Vars
	for i, v := range pdoc.Vars {
		buf.Reset()
		utils.FormatCode(&buf, v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Vars[i] = v
	}

	// Dirs.
	this.Data["IsHasSubdirs"] = len(pdoc.Dirs) > 0
	pinfos := make([]*models.PkgInfo, 0, len(pdoc.Dirs))
	for _, v := range pdoc.Dirs {
		v = pdoc.ImportPath + "/" + v
		if pinfo, err := models.GetPkgInfo(v); err == nil {
			pinfos = append(pinfos, pinfo)
		} else {
			pinfos = append(pinfos, &models.PkgInfo{Path: v})
		}
	}
	this.Data["Subdirs"] = pinfos

	this.Data["Files"] = pdoc.Files
	this.Data["ImportPkgs"] = pdecl.Imports
	this.Data["ImportPkgNum"] = len(pdoc.Imports) - 1
	this.Data["UtcTime"] = pdoc.Created
	this.Data["GOOS"] = pdecl.Goos
	this.Data["GOARCH"] = pdecl.Goarch
	return true
}
Пример #13
0
// Get implemented Get method for HomeController.
// It serves home page of Go Walker.
func (this *HomeController) Get() {
	// Print unusual User-Agent.
	ua := this.Ctx.Request.Header.Get("User-Agent")
	if len(ua) < 20 {
		beego.Trace("User-Agent:", this.Ctx.Request.Header.Get("User-Agent"))
	}

	// Check language version by different ways.
	lang := checkLangVer(this.Ctx.Request, this.Input().Get("lang"))

	// Get language version.
	curLang, restLangs := getLangVer(
		this.Ctx.Request.Header.Get("Accept-Language"), lang)

	// Save language information in cookies.
	this.Ctx.SetCookie("lang", curLang.Lang+";path=/", 0)

	// Get query field.
	q := strings.TrimSpace(this.Input().Get("q"))

	if path, ok := utils.IsBrowseURL(q); ok {
		q = path
	}

	// Get pure URL.
	reqUrl := this.Ctx.Request.RequestURI[1:]
	if i := strings.Index(reqUrl, "?"); i > -1 {
		reqUrl = reqUrl[:i]
	}

	if len(reqUrl) == 0 && len(q) > 0 {
		reqUrl = q
	}

	// Set properties
	this.Layout = "layout_" + curLang.Lang + ".html"

	// Set language properties.
	this.Data["Lang"] = curLang.Lang
	this.Data["CurLang"] = curLang.Name
	this.Data["RestLangs"] = restLangs

	// Check show home page or documentation page.
	if len(reqUrl) == 0 && len(q) == 0 {
		// Home page.
		this.TplNames = "home_" + curLang.Lang + ".html"

		// Recent projects
		this.Data["RecentPros"] = recentViewedPros
		// Get popular project list from database.
		pkgInfos, _ := models.GetPopularPros()
		this.Data["PopPros"] = pkgInfos
		// Set standard library keyword type-ahead.
		this.Data["DataSrc"] = utils.GoRepoSet
	} else {
		// Documentation page.
		broPath := reqUrl // Browse path.

		// Check if it is standard library.
		if utils.IsGoRepoPath(broPath) {
			broPath = "code.google.com/p/go/source/browse/src/pkg/" + broPath
		}

		// Check if it is a remote path that can be used for 'go get', if not means it's a keyword.
		if !utils.IsValidRemotePath(broPath) {
			// Show search page
			this.Redirect("/search?q="+reqUrl, 302)
			return
		}

		// Check documentation of this import path, and update automatically as needed.
		pdoc, err := doc.CheckDoc(reqUrl, doc.HUMAN_REQUEST)
		if err == nil {
			// Generate documentation page.

			/* TODO */

			if pdoc != nil && generatePage(this, pdoc, broPath, curLang.Lang) {
				// Update recent project list.
				updateRecentPros(pdoc)
				// Update project views.
				pinfo := &models.PkgInfo{
					Path:       pdoc.ImportPath,
					Synopsis:   pdoc.Synopsis,
					Created:    pdoc.Created,
					ProName:    pdoc.ProjectName,
					ViewedTime: pdoc.ViewedTime,
					Views:      pdoc.Views,
					Etag:       pdoc.Etag,
				}
				models.AddViews(pinfo)
				return
			}
		} else {
			beego.Error("HomeController.Get():", err)
		}

		// Show search page
		this.Redirect("/search?q="+reqUrl, 302)
		return
	}
}
Пример #14
0
// generatePage genarates documentation page for project.
// it returns false when its a invaild(empty) project.
func generatePage(this *HomeController, pdoc *doc.Package, q string, lang string) bool {
	// Load project data from database.
	pdecl, err := models.LoadProject(pdoc.ImportPath)
	if err != nil {
		beego.Error("HomeController.generatePage():", err)
		return false
	}

	// Set properties.
	this.TplNames = "docs_" + lang + ".html"

	// Refresh (within 10 seconds).
	this.Data["IsRefresh"] = pdoc.Created.Add(10 * time.Second).UTC().After(time.Now().UTC())

	// Get VCS name, project name, project home page, and Upper level project URL.
	this.Data["VCS"], this.Data["ProName"], this.Data["ProPath"], this.Data["ProDocPath"] = getVCSInfo(q, pdoc)

	if utils.IsGoRepoPath(pdoc.ImportPath) &&
		strings.Index(pdoc.ImportPath, ".") == -1 {
		this.Data["IsGoRepo"] = true
	}

	this.Data["Views"] = pdoc.Views + 1

	// Tags.
	this.Data["Tags"] = getTags(pdoc.Tags, lang)

	// Introduction.
	this.Data["ImportPath"] = pdoc.ImportPath
	byts, _ := base32.StdEncoding.DecodeString(pdecl.Doc)
	this.Data["PkgFullIntro"] = string(byts)

	var buf bytes.Buffer
	// Convert data format.
	err = ConvertDataFormat(pdoc, pdecl)
	if err != nil {
		beego.Error("HomeController.generatePage(): ConvertDataFormat", err)
		return false
	}

	links := make([]*utils.Link, 0, len(pdoc.Types)+len(pdoc.Imports)+len(pdoc.Funcs)+10)
	// Get all types, functions and import packages
	for _, t := range pdoc.Types {
		links = append(links, &utils.Link{
			Name:    t.Name,
			Comment: template.HTMLEscapeString(t.Doc),
		})
		buf.WriteString("&quot;" + t.Name + "&quot;,")
	}

	for _, f := range pdoc.Funcs {
		links = append(links, &utils.Link{
			Name:    f.Name,
			Comment: template.HTMLEscapeString(f.Doc),
		})
		buf.WriteString("&quot;" + f.Name + "&quot;,")
	}

	for _, t := range pdoc.Types {
		for _, f := range t.Funcs {
			links = append(links, &utils.Link{
				Name:    f.Name,
				Comment: template.HTMLEscapeString(f.Doc),
			})
			buf.WriteString("&quot;" + f.Name + "&quot;,")
		}

		for _, m := range t.Methods {
			buf.WriteString("&quot;" + t.Name + "." + m.Name + "&quot;,")
		}
	}

	for _, v := range pdoc.Imports {
		links = append(links, &utils.Link{
			Name: path.Base(v) + ".",
			Path: v,
		})
	}

	exportDataSrc := buf.String()
	if len(exportDataSrc) > 0 {
		this.Data["HasExports"] = true
		exportDataSrc = exportDataSrc[:len(exportDataSrc)-1]
		// Set export keyword type-ahead.
		this.Data["ExportDataSrc"] = exportDataSrc
	}

	// Index.
	this.Data["IsHasConst"] = len(pdoc.Consts) > 0
	this.Data["IsHasVar"] = len(pdoc.Vars) > 0
	this.Data["Funcs"] = pdoc.Funcs
	for i, f := range pdoc.Funcs {
		buf.Reset()
		godoc.ToHTML(&buf, f.Doc, nil)
		f.Doc = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, &f.Decl, links)
		f.FmtDecl = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, &f.Code, links)
		f.Code = buf.String()
		pdoc.Funcs[i] = f
	}
	this.Data["Types"] = pdoc.Types
	for i, t := range pdoc.Types {
		for j, f := range t.Funcs {
			buf.Reset()
			godoc.ToHTML(&buf, f.Doc, nil)
			f.Doc = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, &f.Decl, links)
			f.FmtDecl = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, &f.Code, links)
			f.Code = buf.String()
			t.Funcs[j] = f
		}
		for j, m := range t.Methods {
			buf.Reset()
			godoc.ToHTML(&buf, m.Doc, nil)
			m.Doc = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, &m.Decl, links)
			m.FmtDecl = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, &m.Code, links)
			m.Code = buf.String()
			t.Methods[j] = m
		}
		buf.Reset()
		godoc.ToHTML(&buf, t.Doc, nil)
		t.Doc = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, &t.Decl, links)
		t.FmtDecl = buf.String()
		pdoc.Types[i] = t
	}

	// Constants.
	this.Data["Consts"] = pdoc.Consts
	for i, v := range pdoc.Consts {
		buf.Reset()
		v.Decl = template.HTMLEscapeString(v.Decl)
		v.Decl = strings.Replace(v.Decl, "&#34;", "\"", -1)
		utils.FormatCode(&buf, &v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Consts[i] = v
	}

	// Variables.
	this.Data["Vars"] = pdoc.Vars
	for i, v := range pdoc.Vars {
		buf.Reset()
		utils.FormatCode(&buf, &v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Vars[i] = v
	}

	// Dirs.
	this.Data["IsHasSubdirs"] = len(pdoc.Dirs) > 0
	pinfos := make([]*models.PkgInfo, 0, len(pdoc.Dirs))
	for _, v := range pdoc.Dirs {
		v = pdoc.ImportPath + "/" + v
		if pinfo, err := models.GetPkgInfo(v); err == nil {
			pinfos = append(pinfos, pinfo)
		} else {
			pinfos = append(pinfos, &models.PkgInfo{Path: v})
		}
	}
	this.Data["Subdirs"] = pinfos

	// Tags.
	this.Data["TagsDataSrc"] = tagSet

	this.Data["Files"] = pdoc.Files
	this.Data["ImportPkgs"] = pdecl.Imports
	this.Data["ImportPkgNum"] = len(pdoc.Imports) - 1
	this.Data["IsImported"] = pdoc.ImportedNum > 0
	this.Data["ImportPid"] = pdoc.ImportPid
	this.Data["ImportedNum"] = pdoc.ImportedNum
	this.Data["UtcTime"] = pdoc.Created
	this.Data["GOOS"] = pdecl.Goos
	this.Data["GOARCH"] = pdecl.Goarch
	return true
}
Пример #15
0
// Get implemented Get method for HomeRouter.
func (this *HomeRouter) Get() {
	// Get argument(s).
	q := strings.TrimRight(
		strings.TrimSpace(this.Input().Get("q")), "/")

	if path, ok := utils.IsBrowseURL(q); ok {
		q = path
	}

	// Get pure URL.
	reqUrl := this.Ctx.Request.RequestURI[1:]
	if i := strings.Index(reqUrl, "?"); i > -1 {
		reqUrl = reqUrl[:i]
		if path, ok := utils.IsBrowseURL(reqUrl); ok {
			reqUrl = path
		}
	}

	// Redirect to query string.
	if len(reqUrl) == 0 && len(q) > 0 {
		reqUrl = q
		this.Redirect("/"+reqUrl, 302)
		return
	}

	// User History.
	urpids, _ := this.Ctx.Request.Cookie("UserHistory")
	urpts, _ := this.Ctx.Request.Cookie("UHTimestamps")

	if len(reqUrl) == 0 && len(q) == 0 {
		serveHome(this, urpids, urpts)
		return
	}

	// Documentation page.
	broPath := reqUrl // Browse path.

	// Check if it's the standard library.
	if utils.IsGoRepoPath(broPath) {
		broPath = "code.google.com/p/go/source/browse/src/pkg/" + broPath
	} else if utils.IsGoSubrepoPath(broPath) {
		this.Redirect("/code.google.com/p/"+broPath, 301)
		return
	} else if strings.Index(broPath, "source/browse/") > -1 {
		broPath = strings.Replace(broPath, "source/browse/", "", 1)
	}

	// Check if it's a remote path that can be used for 'go get', if not means it's a keyword.
	if !utils.IsValidRemotePath(broPath) {
		// Search.
		this.Redirect("/search?q="+reqUrl, 302)
		return
	}

	// Get tag field.
	tag := strings.TrimSpace(this.Input().Get("tag"))
	if tag == "master" || tag == "default" {
		tag = ""
	}

	// Check documentation of current import path, update automatically as needed.
	pdoc, err := doc.CheckDoc(reqUrl, tag, doc.RT_Human)
	if err == nil {
		// errNoMatch leads to pdoc == nil.
		if pdoc != nil {
			// Generate documentation page.
			if generatePage(this, pdoc, broPath, tag) {
				ps, ts := updateCacheInfo(pdoc, urpids, urpts)
				this.Ctx.SetCookie("UserHistory", ps, 9999999999, "/")
				this.Ctx.SetCookie("UHTimestamps", ts, 9999999999, "/")
				return
			}
		}
		this.Redirect("/search?q="+reqUrl, 302)
		return
	}

	// Error.
	this.Data["IsHasError"] = true
	this.Data["ErrMsg"] = strings.Replace(err.Error(),
		doc.GetGithubCredentials(), "<githubCred>", 1)
	if !strings.Contains(err.Error(), "Cannot find Go files") {
		beego.Error("HomeRouter.Get ->", err)
	}
	serveHome(this, urpids, urpts)
}
Пример #16
0
// DeleteProject deletes everything about the path in database, and update import information.
func DeleteProject(path string) error {
	// Check path length to reduce connect times. (except launchpad.net)
	if path[0] != 'l' && len(strings.Split(path, "/")) <= 2 {
		beego.Error("models.DeleteProject(", path, ") -> Short path as not needed")
		return nil
	}

	q := connDb()
	defer q.Close()

	var i1, i2, i3, i4, i5 int64
	// Delete package information.
	info := new(PkgInfo)
	err := q.WhereEqual("path", path).Find(info)
	if err == nil {
		i1, err = q.WhereEqual("path", path).Delete(info)
		if err != nil {
			beego.Error("models.DeleteProject(", path, ") -> Information:", err)
		}
	}

	// Delete package declaration.
	if info.Id > 0 {
		// Find.
		var pdecls []*PkgDecl
		err = q.WhereEqual("pid", info.Id).FindAll(&pdecls)
		if err != nil {
			beego.Error("models.DeleteProject(", path, ") -> Find declaration:", err)
		}

		// Update.
		if !utils.IsGoRepoPath(path) {
			for _, pd := range pdecls {
				// Don't need to check standard library.
				// Update import information.
				imports := strings.Split(pd.Imports, "|")
				imports = imports[:len(imports)-1]
				for _, v := range imports {
					if !utils.IsGoRepoPath(v) {
						// Only count non-standard library.
						updateImportInfo(q, v, int(info.Id), false)
					}
				}
			}
		}

		// Delete.
		i2, err = q.WhereEqual("pid", info.Id).Delete(new(PkgDecl))
		if err != nil {
			beego.Error("models.DeleteProject(", path, ") -> Delete declaration:", err)
		}
	}

	// Delete package documentation.
	i3, err = q.WhereEqual("path", path).Delete(new(PkgDoc))
	if err != nil {
		beego.Error("models.DeleteProject(", path, ") -> Documentation:", err)
	}

	// Delete package examples.
	i4, err = q.WhereEqual("path", path).Delete(new(PkgExam))
	if err != nil {
		beego.Error("models.DeleteProject(", path, ") -> Examples:", err)
	}

	// Delete package functions.
	if info.Id > 0 {
		i5, err = q.WhereEqual("path", path).Delete(new(PkgExam))
		if err != nil {
			beego.Error("models.DeleteProject(", path, ") -> Functions:", err)
		}
	}

	if i1+i2+i3+i4+i5 > 0 {
		beego.Info("models.DeleteProject(", path, i1, i2, i3, i4, i5, ")")
	}

	return nil
}
Пример #17
0
// generatePage genarates documentation page for project.
// it returns false when its a invaild(empty) project.
func generatePage(this *HomeRouter, pdoc *doc.Package, q, tag, lang string) bool {
	// Load project data from database.
	pdecl, err := models.LoadProject(pdoc.ImportPath, tag)
	if err != nil {
		beego.Error("HomeController.generatePage ->", err)
		return false
	}

	// Set properties.
	this.TplNames = "docs_" + lang + ".html"

	// Refresh (within 10 seconds).
	this.Data["IsRefresh"] = pdoc.Created.Add(10 * time.Second).UTC().After(time.Now().UTC())

	// Get VCS name, project name, project home page, and Upper level project URL.
	this.Data["VCS"], this.Data["ProName"], this.Data["ProPath"], this.Data["ProDocPath"] =
		getVCSInfo(q, tag, pdoc)

	if utils.IsGoRepoPath(pdoc.ImportPath) &&
		strings.Index(pdoc.ImportPath, ".") == -1 {
		this.Data["IsGoRepo"] = true
	}

	this.Data["Views"] = pdoc.Views + 1

	// Labels.
	this.Data["Labels"] = getLabels(pdoc.Labels)

	// Introduction.
	this.Data["ImportPath"] = pdoc.ImportPath
	byts, _ := base32.StdEncoding.DecodeString(
		models.LoadPkgDoc(pdoc.ImportPath, lang, "rm"))
	this.Data["PkgDoc"] = string(byts)
	byts, _ = base32.StdEncoding.DecodeString(pdecl.Doc)
	this.Data["PkgFullIntro"] = string(byts)

	var buf bytes.Buffer
	// Convert data format.
	err = ConvertDataFormat(pdoc, pdecl)
	if err != nil {
		beego.Error("HomeController.generatePage -> ConvertDataFormat:", err)
		return false
	}

	links := make([]*utils.Link, 0, len(pdoc.Types)+len(pdoc.Imports)+len(pdoc.Funcs)+10)
	// Get all types, functions and import packages
	for _, t := range pdoc.Types {
		links = append(links, &utils.Link{
			Name:    t.Name,
			Comment: template.HTMLEscapeString(t.Doc),
		})
		buf.WriteString("&quot;" + t.Name + "&quot;,")
	}

	for _, f := range pdoc.Funcs {
		links = append(links, &utils.Link{
			Name:    f.Name,
			Comment: template.HTMLEscapeString(f.Doc),
		})
		buf.WriteString("&quot;" + f.Name + "&quot;,")
	}

	for _, t := range pdoc.Types {
		for _, f := range t.Funcs {
			links = append(links, &utils.Link{
				Name:    f.Name,
				Comment: template.HTMLEscapeString(f.Doc),
			})
			buf.WriteString("&quot;" + f.Name + "&quot;,")
		}

		for _, m := range t.Methods {
			buf.WriteString("&quot;" + t.Name + "." + m.Name + "&quot;,")
		}
	}

	for _, v := range pdoc.Imports {
		links = append(links, &utils.Link{
			Name: path.Base(v) + ".",
			Path: v,
		})
	}

	exportDataSrc := buf.String()
	if len(exportDataSrc) > 0 {
		this.Data["HasExports"] = true
		exportDataSrc = exportDataSrc[:len(exportDataSrc)-1]
		// Set export keyword type-ahead.
		this.Data["ExportDataSrc"] = exportDataSrc
	}

	// Commented and total objects number.
	var comNum, totalNum int

	// Index.
	this.Data["IsHasConst"] = len(pdoc.Consts) > 0
	this.Data["IsHasVar"] = len(pdoc.Vars) > 0

	// Constants.
	this.Data["Consts"] = pdoc.Consts
	for i, v := range pdoc.Consts {
		buf.Reset()
		v.Decl = template.HTMLEscapeString(v.Decl)
		v.Decl = strings.Replace(v.Decl, "&#34;", "\"", -1)
		utils.FormatCode(&buf, &v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Consts[i] = v
	}

	// Variables.
	this.Data["Vars"] = pdoc.Vars
	for i, v := range pdoc.Vars {
		buf.Reset()
		utils.FormatCode(&buf, &v.Decl, links)
		v.FmtDecl = buf.String()
		pdoc.Vars[i] = v
	}

	this.Data["Funcs"] = pdoc.Funcs
	for i, f := range pdoc.Funcs {
		if len(f.Doc) > 0 {
			buf.Reset()
			godoc.ToHTML(&buf, f.Doc, nil)
			f.Doc = buf.String()
			comNum++
		}
		buf.Reset()
		utils.FormatCode(&buf, &f.Decl, links)
		f.FmtDecl = buf.String()
		buf.Reset()
		utils.FormatCode(&buf, &f.Code, links)
		f.Code = buf.String()
		if exs := getExamples(pdoc, "", f.Name); len(exs) > 0 {
			f.IsHasExam = true
			f.Exams = exs
		}
		totalNum++
		pdoc.Funcs[i] = f
	}

	this.Data["Types"] = pdoc.Types
	for i, t := range pdoc.Types {
		for j, f := range t.Funcs {
			if len(f.Doc) > 0 {
				buf.Reset()
				godoc.ToHTML(&buf, f.Doc, nil)
				f.Doc = buf.String()
				comNum++
			}
			buf.Reset()
			utils.FormatCode(&buf, &f.Decl, links)
			f.FmtDecl = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, &f.Code, links)
			f.Code = buf.String()
			if exs := getExamples(pdoc, "", f.Name); len(exs) > 0 {
				f.IsHasExam = true
				f.Exams = exs
			}
			totalNum++
			t.Funcs[j] = f
		}
		for j, m := range t.Methods {
			if len(m.Doc) > 0 {
				buf.Reset()
				godoc.ToHTML(&buf, m.Doc, nil)
				m.Doc = buf.String()
				comNum++
			}
			buf.Reset()
			utils.FormatCode(&buf, &m.Decl, links)
			m.FmtDecl = buf.String()
			buf.Reset()
			utils.FormatCode(&buf, &m.Code, links)
			m.Code = buf.String()
			if exs := getExamples(pdoc, t.Name, m.Name); len(exs) > 0 {
				m.IsHasExam = true
				m.Exams = exs
			}
			totalNum++
			t.Methods[j] = m
		}
		if len(t.Doc) > 0 {
			buf.Reset()
			godoc.ToHTML(&buf, t.Doc, nil)
			t.Doc = buf.String()
			comNum++
		}
		buf.Reset()
		utils.FormatCode(&buf, &t.Decl, links)
		t.FmtDecl = buf.String()
		if exs := getExamples(pdoc, "", t.Name); len(exs) > 0 {
			t.IsHasExam = true
			t.Exams = exs
		}
		totalNum++
		pdoc.Types[i] = t
	}

	if !pdoc.IsCmd {
		// Calculate documentation complete %.
		this.Data["DocCPLabel"], this.Data["DocCP"] = calDocCP(comNum, totalNum)

		// Examples.
		this.Data["IsHasExams"] = len(pdoc.Examples)+len(pdoc.UserExamples) > 0
		this.Data["Exams"] = append(pdoc.Examples, pdoc.UserExamples...)

		// Tags.
		this.Data["IsHasTags"] = len(pdoc.Tags) > 1
		if len(tag) == 0 {
			tag = "master"
		}
		this.Data["CurTag"] = tag
		this.Data["Tags"] = pdoc.Tags
	} else {
		this.Data["IsCmd"] = true
	}

	// Dirs.
	this.Data["IsHasSubdirs"] = len(pdoc.Dirs) > 0
	pinfos := make([]*models.PkgInfo, 0, len(pdoc.Dirs))
	for _, v := range pdoc.Dirs {
		v = pdoc.ImportPath + "/" + v
		if pinfo, err := models.GetPkgInfo(v, tag); err == nil {
			pinfos = append(pinfos, pinfo)
		} else {
			pinfos = append(pinfos, &models.PkgInfo{Path: v})
		}
	}
	this.Data["Subdirs"] = pinfos

	// Labels.
	this.Data["LabelDataSrc"] = labelSet

	this.Data["Files"] = pdoc.Files
	this.Data["ImportPkgs"] = pdecl.Imports
	this.Data["ImportPkgNum"] = len(pdoc.Imports) - 1
	this.Data["IsImported"] = pdoc.ImportedNum > 0
	this.Data["ImportPid"] = pdoc.ImportPid
	this.Data["ImportedNum"] = pdoc.ImportedNum
	this.Data["UtcTime"] = pdoc.Created
	return true
}
Пример #18
0
// SaveProject saves package information, declaration and functions;
// update import information.
func SaveProject(pinfo *hv.PkgInfo, pdecl *PkgDecl, pfuncs []*PkgFunc, imports []string) error {
	q := connDb()
	defer q.Close()

	// Load package information(save after checked import information).
	info := new(hv.PkgInfo)
	err := q.WhereEqual("import_path", pinfo.ImportPath).Find(info)
	if err == nil {
		pinfo.Id = info.Id
	}

	// ------------------------------
	// Update imported information.
	// ------------------------------

	isMaster := pdecl != nil && len(pdecl.Tag) == 0
	if info.Id > 0 {
		// Current package.
		importeds := strings.Split(info.RefPids, "|")
		importPids := make([]string, 0, len(importeds))
		for _, v := range importeds {
			pid, _ := strconv.ParseInt(v, 10, 64)
			if checkImport(q, info.ImportPath, pid) {
				importPids = append(importPids, v)
			}
		}

		pinfo.RefPids = strings.Join(importPids, "|")
		pinfo.RefNum = len(importPids)
	}

	if isMaster {
		pimp := new(PkgImport)
		err := q.WhereEqual("path", pinfo.ImportPath).Find(pimp)
		if err == nil {
			importPids := strings.Split(pinfo.RefPids, "|")
			pimps := strings.Split(pimp.Imports, "|")
			for _, v := range pimps {
				if len(v) == 0 {
					continue
				}
				pid, _ := strconv.ParseInt(v, 10, 64)
				if i := getRefIndex(importPids, v); i == -1 &&
					checkImport(q, info.ImportPath, pid) {
					importPids = append(importPids, v)
				}
			}
			q.WhereEqual("id", pimp.Id).Delete(pimp)
			pinfo.RefPids = strings.Join(importPids, "|")
			pinfo.RefNum = len(importPids)
			if pinfo.RefNum > 0 && strings.HasPrefix(pinfo.RefPids, "|") {
				pinfo.RefPids = pinfo.RefPids[1:]
				pinfo.RefNum--
			}
		}

	} else {
		pinfo.Ptag = info.Ptag
	}

	_, err = q.Save(pinfo)
	if err != nil {
		beego.Error("models.SaveProject(", pinfo.ImportPath, ") -> Information2:", err)
	}

	// Don't need to check standard library and non-master projects.
	if imports != nil && isMaster && !utils.IsGoRepoPath(pinfo.ImportPath) {
		// Other packages.
		for _, v := range imports {
			if !utils.IsGoRepoPath(v) {
				// Only count non-standard library.
				updateImportInfo(q, v, int(pinfo.Id), int(pinfo.Rank), true)
			}
		}
	}
	// ------------- END ------------

	// Save package declaration.
	decl := new(PkgDecl)
	if pdecl != nil {
		cond := qbs.NewCondition("pid = ?", pinfo.Id).And("tag = ?", pdecl.Tag)
		err = q.Condition(cond).Find(decl)
		if err == nil {
			pdecl.Id = decl.Id
		}

		pdecl.Pid = pinfo.Id
		_, err = q.Save(pdecl)
		if err != nil {
			beego.Error("models.SaveProject(", pinfo.ImportPath, ") -> Declaration:", err)
		}

		// ------------------------------
		// Save package tag.
		// ------------------------------

		proPath := utils.GetProjectPath(pinfo.ImportPath)
		if utils.IsGoRepoPath(pinfo.ImportPath) {
			proPath = "code.google.com/p/go"
		}
		pkgTag := new(PkgTag)
		cond = qbs.NewCondition("path = ?", proPath).And("tag = ?", pdecl.Tag)
		err = q.Condition(cond).Find(pkgTag)
		if err != nil {
			pkgTag.Path = proPath
			pkgTag.Tag = pdecl.Tag
		}
		pkgTag.Vcs = pinfo.Vcs
		pkgTag.Tags = pinfo.Tags

		_, err = q.Save(pkgTag)
		if err != nil {
			beego.Error("models.SaveProject(", pinfo.ImportPath, ") -> PkgTag:", err)
		}

		// ------------- END ------------
	}

	// ------------------------------
	// Save package functions.
	// ------------------------------

	if pfuncs != nil {
		// Old package need to clean old data.
		if decl.Id > 0 {
			// Update all old functions' 'IsOle' to be true.
			type pkgFunc struct {
				IsOld bool
			}
			pfunc := new(pkgFunc)
			pfunc.IsOld = true
			_, err = q.WhereEqual("pid", pdecl.Id).Update(pfunc)
		}

		// Save new ones.
		for _, pf := range pfuncs {
			f := new(PkgFunc)
			cond := qbs.NewCondition("pid = ?", pdecl.Id).And("name = ?", pf.Name)
			err = q.Condition(cond).Find(f)
			if err == nil {
				pf.Id = f.Id
			}

			pf.Pid = pdecl.Id
			_, err = q.Save(pf)
			if err != nil {
				beego.Error("models.SaveProject(", pinfo.ImportPath, ") -> Update function(", pf.Name, "):", err)
			}
		}

		if decl.Id > 0 {
			// Delete old ones if exist.
			cond := qbs.NewCondition("pid = ?", pdecl.Id).And("is_old = ?", true)
			_, err = q.Condition(cond).Delete(new(PkgFunc))
			if err != nil {
				beego.Error("models.SaveProject(", pinfo.ImportPath, ") -> Delete functions:", err)
			}
		}
	}

	// ------------- END ------------

	return nil
}
Пример #19
0
// DeleteProject deletes everything of the package,
// and update import information.
func DeleteProject(path string) {
	// Check path length to reduce connect times(except launchpad.net).
	if path[0] != 'l' && len(strings.Split(path, "/")) <= 2 {
		beego.Trace("models.DeleteProject(", path, ") -> Short path as not needed")
		return
	}

	var i1, i2, i3, i4, i5 int64
	// Delete package information.
	// TODO: NEED TO DELETE ALL SUB-PEOJECTS.
	info := &hv.PkgInfo{ImportPath: path}
	has, err := x.Get(info)
	if err != nil {
		beego.Error("models.DeleteProject(", path, ") -> Get hv.PkgInfo", err)
		return
	}
	if has {
		i1, err = x.Where("import_path = ?", path).Delete(info)
		if err != nil {
			beego.Error("models.DeleteProject(", path, ") -> Information:", err)
		}
	}

	// Delete package declaration.
	if info.Id > 0 {
		// Find.
		var pdecls []PkgDecl
		err = x.Where("pid = ?", info.Id).Find(&pdecls)
		if err != nil {
			beego.Error("models.DeleteProject(", path, ") -> Find declaration:", err)
		}

		// Update.
		if !utils.IsGoRepoPath(path) {
			for _, pd := range pdecls {
				// Don't need to check standard library.
				// Update import information.
				imports := strings.Split(pd.Imports, "|")
				imports = imports[:len(imports)-1]
				for _, v := range imports {
					if !utils.IsGoRepoPath(v) {
						// Only count non-standard library.
						updateImportInfo(v, int(info.Id), 0, false)
					}
				}
			}
		}

		// Delete.
		i2, err = x.Where("pid = ?", info.Id).Delete(new(PkgDecl))
		if err != nil {
			beego.Error("models.DeleteProject(", path, ") -> Delete declaration:", err)
		}
	}

	// Delete package examples.
	i4, err = x.Where("path = ?", path).Delete(new(PkgExam))
	if err != nil {
		beego.Error("models.DeleteProject(", path, ") -> Examples:", err)
	}

	// Delete package functions.
	if info.Id > 0 {
		i5, err = x.Where("path = ?", path).Delete(new(PkgExam))
		if err != nil {
			beego.Error("models.DeleteProject(", path, ") -> Functions:", err)
		}
	}

	if i1+i2+i3+i4+i5 > 0 {
		beego.Info("models.DeleteProject(", path, i1, i2, i3, i4, i5, ")")
	}

	return
}
Пример #20
0
// SaveProject saves package information, declaration and functions;
// update import information.
func SaveProject(pinfo *hv.PkgInfo, pdecl *PkgDecl, pfuncs []PkgFunc, imports []string) error {
	// Load package information(save after checked import information).
	info := &hv.PkgInfo{ImportPath: pinfo.ImportPath}
	has, err := x.Get(info)
	if err != nil {
		return errors.New(
			fmt.Sprintf("models.SaveProject( %s ) -> Get hv.PkgInfo: %s",
				pinfo.ImportPath, err))
	}
	if has {
		pinfo.Id = info.Id
	}

	// ------------------------------
	// Update imported information.
	// ------------------------------

	isMaster := pdecl != nil && len(pdecl.Tag) == 0
	if info.Id > 0 {
		// Current package.
		importeds := strings.Split(info.RefPids, "|")
		importPids := make([]string, 0, len(importeds))
		for _, v := range importeds {
			pid, _ := strconv.ParseInt(v, 10, 64)
			if checkImport(info.ImportPath, pid) {
				importPids = append(importPids, v)
			}
		}

		pinfo.RefPids = strings.Join(importPids, "|")
		pinfo.RefNum = len(importPids)
	}

	if isMaster {
		pimp := &PkgImport{Path: pinfo.ImportPath}
		has, err := x.Get(pimp)
		if err != nil {
			return errors.New(
				fmt.Sprintf("models.SaveProject( %s ) -> Get PkgImport: %s",
					pinfo.ImportPath, err))
		}
		if has {
			importPids := strings.Split(pinfo.RefPids, "|")
			pimps := strings.Split(pimp.Imports, "|")
			for _, v := range pimps {
				if len(v) == 0 {
					continue
				}
				pid, _ := strconv.ParseInt(v, 10, 64)
				if i := getRefIndex(importPids, v); i == -1 &&
					checkImport(info.ImportPath, pid) {
					importPids = append(importPids, v)
				}
			}
			_, err := x.Id(pimp.Id).Delete(pimp)
			if err != nil {
				beego.Error("models.SaveProject(", pinfo.ImportPath,
					") -> Delete PkgImport:", err.Error())
			}

			pinfo.RefPids = strings.Join(importPids, "|")
			pinfo.RefNum = len(importPids)
			if pinfo.RefNum > 0 && strings.HasPrefix(pinfo.RefPids, "|") {
				pinfo.RefPids = pinfo.RefPids[1:]
				pinfo.RefNum--
			}
		}

	} else {
		pinfo.Ptag = info.Ptag
	}

	if has {
		_, err = x.Id(pinfo.Id).UseBool("is_cgo").Update(pinfo)
	} else {
		_, err = x.Insert(pinfo)
	}
	if err != nil {
		beego.Error("models.SaveProject(", pinfo.ImportPath, ") -> Information2:", err)
	}

	// Don't need to check standard library and non-master projects.
	if imports != nil && isMaster && !utils.IsGoRepoPath(pinfo.ImportPath) {
		// Other packages.
		for _, v := range imports {
			if !utils.IsGoRepoPath(v) && v != "C" {
				// Only count non-standard library.
				updateImportInfo(v, int(pinfo.Id), int(pinfo.Rank), true)
			}
		}
	}
	// ------------- END ------------

	// Save package declaration.
	decl := new(PkgDecl)
	if pdecl != nil {
		has, err := x.Where("pid = ?", pinfo.Id).And("tag = ?", pdecl.Tag).Get(decl)
		if err != nil {
			beego.Error("models.SaveProject(", pinfo.Id, pdecl.Tag,
				") -> Get PkgDecl:", err.Error())
		}
		if has {
			pdecl.Id = decl.Id
		}

		pdecl.Pid = pinfo.Id
		if has {
			_, err = x.Id(pdecl.Id).Update(pdecl)
		} else {
			_, err = x.Insert(pdecl)
		}
		if err != nil {
			beego.Error("models.SaveProject(", pinfo.ImportPath, ") -> Declaration:", err)
		}

		// ------------------------------
		// Save package tag.
		// ------------------------------

		proPath := utils.GetProjectPath(pinfo.ImportPath)
		if utils.IsGoRepoPath(pinfo.ImportPath) {
			proPath = "code.google.com/p/go"
		}
		pkgTag := &PkgTag{
			Path: proPath,
			Tag:  pdecl.Tag,
		}
		has, err = x.Get(pkgTag)
		if err != nil {
			beego.Error("models.SaveProject(", proPath, pdecl.Tag, ") -> Get PkgTag:", err)
		}
		if !has {
			pkgTag.Path = proPath
			pkgTag.Tag = pdecl.Tag
		}
		pkgTag.Vcs = pinfo.Vcs
		pkgTag.Tags = pinfo.Tags

		if has {
			_, err = x.Id(pkgTag.Id).Update(pkgTag)
		} else {
			_, err = x.Insert(pkgTag)
		}
		if err != nil {
			beego.Error("models.SaveProject(", pinfo.ImportPath, ") -> Save PkgTag:", err)
		}

		// ------------- END ------------
	}

	// ------------------------------
	// Save package functions.
	// ------------------------------

	if pfuncs != nil {
		// Old package need to clean old data.
		if decl.Id > 0 {
			// Update all old functions' 'IsOle' to be true.
			type pkgFunc struct {
				IsOld bool
			}
			pfunc := &pkgFunc{IsOld: true}
			_, err = x.Where("pid = ?", pdecl.Id).UseBool().Update(pfunc)
			if err != nil {
				beego.Error("models.SaveProject(", pdecl.Id, ") -> Mark function old:", err)
			}
		}

		// Save new ones.
		for _, pf := range pfuncs {
			f := &PkgFunc{
				Pid:  pdecl.Id,
				Name: pf.Name,
			}
			has, err := x.Get(f)
			if err != nil {
				beego.Error("models.SaveProject(", pdecl.Id, ") -> Get PkgFunc:", err)
				continue
			}
			if has {
				pf.Id = f.Id
			}

			pf.Pid = pdecl.Id
			if has {
				_, err = x.Id(pf.Id).UseBool().Update(pf)
			} else {
				_, err = x.Insert(pf)
			}
			if err != nil {
				beego.Error("models.SaveProject(", pinfo.ImportPath, ") -> Update function(", pf.Name, "):", err)
			}
		}

		if decl.Id > 0 {
			// Delete old ones if exist.
			_, err := x.Where("pid = ?", pdecl.Id).And("is_old = ?", true).Delete(new(PkgFunc))
			if err != nil {
				beego.Error("models.SaveProject(", pinfo.ImportPath, ") -> Delete functions:", err)
			}
		}
	}

	// ------------- END ------------

	return nil
}
Пример #21
0
// SaveProject saves package information, declaration and functions;
// update import information.
func SaveProject(pinfo *PkgInfo, pdecl *PkgDecl, pfuncs []*PkgFunc, imports []string) error {
	q := connDb()
	defer q.Close()

	// Load package information(save after checked import information).
	info := new(PkgInfo)
	err := q.WhereEqual("path", pinfo.Path).Find(info)
	if err == nil {
		pinfo.Id = info.Id
	}

	// Save package declaration.
	decl := new(PkgDecl)
	if pdecl != nil {
		cond := qbs.NewCondition("pid = ?", pinfo.Id).And("tag = ?", pdecl.Tag)
		err = q.Condition(cond).Find(decl)
		if err == nil {
			pdecl.Id = decl.Id
		}

		pdecl.Pid = pinfo.Id
		_, err = q.Save(pdecl)
		if err != nil {
			beego.Error("models.SaveProject(", pinfo.Path, ") -> Declaration:", err)
		}
	}

	// ------------------------------
	// Save package functions.
	// ------------------------------

	if pfuncs != nil {
		// Old package need to clean old data.
		if decl.Id > 0 {
			// Update all old functions' 'IsOle' to be true.
			type pkgFunc struct {
				IsOld bool
			}
			pfunc := new(pkgFunc)
			pfunc.IsOld = true
			_, err = q.WhereEqual("pid", pdecl.Id).Update(pfunc)
		}

		isMaster := pdecl.Tag == ""
		// Save new ones.
		for _, pf := range pfuncs {
			f := new(PkgFunc)
			cond := qbs.NewCondition("pid = ?", pdecl.Id).And("name = ?", pf.Name)
			err = q.Condition(cond).Find(f)
			if err == nil {
				pf.Id = f.Id
			}

			pf.Pid = pdecl.Id
			pf.IsMaster = isMaster
			_, err = q.Save(pf)
			if err != nil {
				beego.Error("models.SaveProject(", pinfo.Path, ") -> Update function(", pf.Name, "):", err)
			}
		}

		if decl.Id > 0 {
			// Delete old ones if exist.
			cond := qbs.NewCondition("pid = ?", pdecl.Id).And("is_old = ?", true)
			_, err = q.Condition(cond).Delete(new(PkgFunc))
			if err != nil {
				beego.Error("models.SaveProject(", pinfo.Path, ") -> Delete functions:", err)
			}
		}
	}

	// ------------- END ------------

	// ------------------------------
	// Update imported information.
	// ------------------------------

	if info.Id > 0 {
		// Current package.
		importeds := strings.Split(
			strings.Replace(info.ImportPid, "$", "", -1), "|")
		importPids := make([]string, 0, len(importeds))
		for _, v := range importeds {
			pid, _ := strconv.ParseInt(v, 10, 64)
			if checkImport(q, info.Path, pid) {
				importPids = append(importPids, "$"+v)
			}
		}
		pinfo.ImportPid = strings.Join(importPids, "|")
		pinfo.ImportedNum = len(importPids)
	}

	_, err = q.Save(pinfo)
	if err != nil {
		beego.Error("models.SaveProject(", pinfo.Path, ") -> Information:", err)
	}

	// Don't need to check standard library.
	if imports != nil && !utils.IsGoRepoPath(pinfo.Path) {
		// Other packages.
		for _, v := range imports {
			if !utils.IsGoRepoPath(v) {
				// Only count non-standard library.
				updateImportInfo(q, v, int(pinfo.Id), true)
			}
		}
	}
	// ------------- END ------------

	return nil
}
Пример #22
0
// GetPkgInfo returns 'PkgInfo' by given import path and tag.
// It returns error when the package does not exist.
func GetPkgInfo(path, tag string) (*hv.PkgInfo, error) {
	// Check path length to reduce connect times.
	if len(path) == 0 {
		return nil, errors.New("models.GetPkgInfo -> Empty path as not found.")
	}

	pinfo := &hv.PkgInfo{ImportPath: path}
	has, err := x.Get(pinfo)
	if !has || err != nil {
		return pinfo, errors.New(
			fmt.Sprintf("models.GetPkgInfo( %s:%s ) -> Get hv.PkgInfo: %v",
				path, tag, err))
	}

	proPath := utils.GetProjectPath(path)
	if utils.IsGoRepoPath(path) {
		proPath = "code.google.com/p/go"
	}
	beego.Trace("models.GetPkgInfo -> proPath:", proPath)

	ptag := &PkgTag{
		Path: proPath,
		Tag:  tag,
	}
	has, err = x.Get(ptag)
	if !has || err != nil {
		pinfo.Ptag = "ptag"
		return pinfo, errors.New(
			fmt.Sprintf("models.GetPkgInfo( %s:%s ) -> Get PkgTag: %v",
				path, tag, err))
	}

	pinfo.Vcs = ptag.Vcs
	pinfo.Tags = ptag.Tags

	// Only 'PkgInfo' cannot prove that package exists,
	// we have to check 'PkgDecl' as well in case it was deleted by mistake.

	pdecl := &PkgDecl{
		Pid: pinfo.Id,
		Tag: tag,
	}
	has, err = x.Get(pdecl)
	if err != nil {
		return pinfo, errors.New(
			fmt.Sprintf("models.GetPkgInfo( %s:%s ) -> Get PkgDecl: %v", path, tag, err))
	}
	if !has {
		pinfo.PkgVer = 0
		pinfo.Ptag = "ptag"
		return pinfo, errors.New(
			fmt.Sprintf("models.GetPkgInfo( %s:%s ) -> PkgDecl not exist: %v", path, tag, err))
	}

	docPath := path + utils.TagSuffix("-", tag)
	if !com.IsExist("." + utils.DocsJsPath + docPath + ".js") {
		pinfo.PkgVer = 0
		pinfo.Ptag = "ptag"
		return pinfo, errors.New(
			fmt.Sprintf("models.GetPkgInfo( %s:%s ) -> JS: File not found", path, tag))
	}

	return pinfo, nil
}
Пример #23
0
// Get implemented Get method for HomeRouter.
func (this *HomeRouter) Get() {
	// Filter unusual User-Agent.
	ua := this.Ctx.Request.Header.Get("User-Agent")
	if len(ua) < 20 {
		beego.Warn("User-Agent:", this.Ctx.Request.Header.Get("User-Agent"))
		return
	}

	// Set language version.
	curLang := setLangVer(this.Ctx, this.Input(), this.Data)

	// Get query field.
	q := strings.TrimSpace(this.Input().Get("q"))

	// Remove last "/".
	q = strings.TrimRight(q, "/")

	if path, ok := utils.IsBrowseURL(q); ok {
		q = path
	}

	// Get pure URL.
	reqUrl := this.Ctx.Request.RequestURI[1:]
	if i := strings.Index(reqUrl, "?"); i > -1 {
		reqUrl = reqUrl[:i]
		if path, ok := utils.IsBrowseURL(reqUrl); ok {
			reqUrl = path
		}
	}

	// Redirect to query string.
	if len(reqUrl) == 0 && len(q) > 0 {
		reqUrl = q
		this.Redirect("/"+reqUrl, 302)
		return
	}

	// Check show home page or documentation page.
	if len(reqUrl) == 0 && len(q) == 0 {
		// Home page.
		this.Data["IsHome"] = true
		this.TplNames = "home_" + curLang.Lang + ".html"

		// Recent projects
		this.Data["RecentPros"] = recentViewedPros
		// Get popular project and examples list from database.
		this.Data["PopPros"], this.Data["RecentExams"] = models.GetPopulars(20, 12)
		// Set standard library keyword type-ahead.
		this.Data["DataSrc"] = utils.GoRepoSet
	} else {
		// Documentation page.
		this.TplNames = "docs_" + curLang.Lang + ".html"
		broPath := reqUrl // Browse path.

		// Check if it is standard library.
		if utils.IsGoRepoPath(broPath) {
			broPath = "code.google.com/p/go/source/browse/src/pkg/" + broPath
		}

		// Check if it is a remote path that can be used for 'gopm get', if not means it's a keyword.
		if !utils.IsValidRemotePath(broPath) {
			// Show search page
			this.Redirect("/search?q="+reqUrl, 302)
			return
		}

		// Get tag field.
		tag := strings.TrimSpace(this.Input().Get("tag"))
		if tag == "master" || tag == "default" {
			tag = ""
		}

		// Check documentation of this import path, and update automatically as needed.
		pdoc, err := doc.CheckDoc(reqUrl, tag, doc.HUMAN_REQUEST)
		if err == nil || pdoc == nil {
			pdoc.UserExamples = getUserExamples(pdoc.ImportPath)
			// Generate documentation page.
			if generatePage(this, pdoc, broPath, tag, curLang.Lang) {
				// Update recent project list.
				updateRecentPros(pdoc)
				// Update project views.
				pinfo := &models.PkgInfo{
					Path:        pdoc.ImportPath,
					Synopsis:    pdoc.Synopsis,
					Created:     pdoc.Created,
					ProName:     pdoc.ProjectName,
					ViewedTime:  pdoc.ViewedTime,
					Views:       pdoc.Views,
					IsCmd:       pdoc.IsCmd,
					Etag:        pdoc.Etag,
					Labels:      pdoc.Labels,
					Tags:        strings.Join(pdoc.Tags, "|||"),
					ImportedNum: pdoc.ImportedNum,
					ImportPid:   pdoc.ImportPid,
				}
				models.AddViews(pinfo)
				return
			}
		} else {
			beego.Error("HomeRouter.Get ->", err)
		}

		// Show search page
		this.Redirect("/search?q="+reqUrl, 302)
		return
	}
}