关于Gogs的一些笔记

我这人比较笨,老大让我看看Gogs,我看了半天才搞懂它的执行流程。又怕到时候忘了,只好边看边做点笔记。毕竟老话说得好,好记性不如烂笔头嘛。
Gogs从gogs.gomain函数开始执行,如果我们从浏览器访问,会进入cmd.web模块。cmd.web模块通过Macaron注册了各种路由规则:

m := newMacaron()
...
m.Get("/", ignSignIn, routes.Home)
m.Group("/explore", func() {
    m.Get("", func(c *context.Context) {
        c.Redirect(setting.AppSubURL + "/explore/repos")
    })
    m.Get("/repos", routes.ExploreRepos)
    m.Get("/users", routes.ExploreUsers)
    m.Get("/organizations", routes.ExploreOrganizations)
}, ignSignIn)
m.Combo("/install", routes.InstallInit).Get(routes.Install).
    Post(bindIgnErr(form.Install{}), routes.InstallPost)
m.Get("/^:type(issues|pulls)$", reqSignIn, user.Issues)
...
m.Group("/repo", func() {
    m.Get("/create", repo.Create)
    m.Post("/create", bindIgnErr(form.CreateRepo{}), repo.CreatePost)
    m.Get("/migrate", repo.Migrate)
    m.Post("/migrate", bindIgnErr(form.MigrateRepo{}), repo.MigratePost)
    m.Combo("/fork/:repoid").Get(repo.Fork).
        Post(bindIgnErr(form.CreateRepo{}), repo.ForkPost)
}, reqSignIn)
...

接下来我从创建仓库这一动作着手分析Gogs如何创建远端Git仓库以及如何在数据库里保存相关信息。
在浏览器里输入:

http://localhost:3000/repo/create

进入仓库创建页面,输入相关信息以后,点击创建仓库,接下来会进入repo.CreatePost 方法。
这个方法首先会将表格里的信息提取出来,然后通过调用models模块的 CreateRepository方法完成仓库的创建以及数据库的记录:

func CreatePost(c *context.Context, f form.CreateRepo) {
    ...
    c.Data["Gitignores"] = models.Gitignores
    c.Data["Licenses"] = models.Licenses
    c.Data["Readmes"] = models.Readmes

        ...

    repo, err := models.CreateRepository(c.User, ctxUser, models.CreateRepoOptions{
        Name:        f.RepoName,
        Description: f.Description,
        Gitignores:  f.Gitignores,
        License:     f.License,
        Readme:      f.Readme,
        IsPrivate:   f.Private || setting.Repository.ForcePrivate,
        AutoInit:    f.AutoInit,
    })
    ...
}

这里的 CreateRepository方法通过调用createRepository向数据库里插入数据,调用initRepository初始化远程仓库。并运用Transaction保证了数据库的内容与仓库的内容一致

// CreateRepository creates a repository for given user or organization.
func CreateRepository(doer, owner *User, opts CreateRepoOptions) (_ *Repository, err error) {
    ...
    repo := &Repository{
        OwnerID:      owner.ID,
        ...
    }

    sess := x.NewSession()
    defer sess.Close()
    if err = sess.Begin(); err != nil {
        return nil, err
    }

    if err = createRepository(sess, doer, owner, repo); err != nil {
        return nil, err
    }

    // No need for init mirror.
    if !opts.IsMirror {
        repoPath := RepoPath(owner.Name, repo.Name)
        if err = initRepository(sess, repoPath, doer, repo, opts); err != nil {
            RemoveAllWithNotice("Delete repository for initialization failure", repoPath)
            return nil, fmt.Errorf("initRepository: %v", err)
        }
        ...
    }
    return repo, sess.Commit()
}

整个应用的大致流程就是这个样子。值得一提的是之前并不知道go怎么执行git命令,后来看了下源码,大概就是运用os.exec传递需要执行的命令以及参数来执行git命令。

你可能感兴趣的:(关于Gogs的一些笔记)