func (this *CHistoryOrderMgr) addRoutine() { for { select { case arge := <-chanAddHistory: id, err := this.myOrm.Insert(arge.order) if err != nil { beego.Warning(err.Error()) break } arge.order.Id = int32(id) arge.done <- true case argeu := <-chanUpdateHistory: _, err := this.myOrm.Update(argeu) if err != nil { beego.Warning(err.Error()) break } case arged := <-chanDelHistory: _, err := this.myOrm.Delete(arged) if err != nil { beego.Warning(err.Error()) break } } } }
func AuthWithWeiXin(openid, token string) (*User, int) { authUser, errNum := utils.AuthWithWeiXin(openid, token) if errNum > 0 { return nil, errNum } o := orm.NewOrm() err := o.Begin() if err != nil { beego.Warning("AuthWithWeiXin fail: ", err) return nil, utils.ERROR_CODE_SYSTEM_ERROR } user := getUserByWeiXinInternal(&o, &authUser.Openid) user, errNum = createOrUpdateUserInternal(&o, user, authUser, "AuthWithWeiXin fail: ", utils.SNS_PLATFORM_WEIXIN) if errNum > 0 { o.Rollback() return nil, errNum } err = o.Commit() if err != nil { beego.Warning("AuthWithWeiXin fail: commit fail ", err) o.Rollback() return nil, utils.ERROR_CODE_SYSTEM_ERROR } return user, 0 }
func readNewMessages(s session.Store, messageIds []int64) Data { userName := "" if s.Get("UserName") != nil { userName = s.Get("UserName").(string) } if userName == "" { beego.Error("No user name available.") return Data{} } messages := models.GetMessagesFromDatabase(userName) for i := len(messages) - 1; i >= 0; i-- { beego.Warning(len(messages), i) for j := 0; j < len(messageIds); j++ { beego.Warning(messages[i], j, messageIds[j]) if messages[i]["Id"] == messageIds[j] { messages = append(messages[:i], messages[i+1:]...) break } } } return Data{ "Messages": messages, } }
// TODO return more detailed error number // NOTE: this will do a fully update, so the user must be read from DB, and then update its field func UpdateUser(user *User) int { o := orm.NewOrm() err := o.Begin() if err != nil { beego.Warning("UpdateUser fail: ", err) return utils.ERROR_CODE_SYSTEM_ERROR } var errNum int for i := 0; i < DB_UNIQUE_CONFLICT_TRY; i++ { user.UpdateAt = utils.GetTimeMillis() errNum = updateUserInternal(&o, user) if errNum == 0 { break } time.Sleep(1 * time.Millisecond) } if errNum > 0 { o.Rollback() return errNum } else { err = o.Commit() if err != nil { beego.Warning("UpdateUser fail: commit fail ", err) o.Rollback() return utils.ERROR_CODE_SYSTEM_ERROR } } return 0 }
func (this *CProductMgr) addRoutine() { for { select { case arge := <-chanAddProduct: id, err := this.myOrm.Insert(arge.product) if err != nil { beego.Warning(err.Error()) break } arge.product.Id = int32(id) arge.done <- true case argeu := <-chanUpdateProduct: _, err := this.myOrm.Update(argeu) if err != nil { beego.Warning(err.Error()) break } case arged := <-chanDelProduct: _, err := this.myOrm.Delete(arged) if err != nil { beego.Warning(err.Error()) break } } } }
func cloneProject(s session.Store, projectName string) Data { // if user is not logged in return userName := "" if s.Get("UserName") != nil { userName = s.Get("UserName").(string) } if userName == "" { beego.Error("No user name available.") return Data{} } beego.Warning("Entering cloneProject with", userName, "and", projectName) if projectName == "" { beego.Error("No project name available.") return Data{} } // Check for rights // Maybe add a token check here, otherwise manipulated clients can clone any project models.CloneProjectDir(userName, projectName, false) return Data{ "ProjectName": projectName, } }
func VerifyUserByPhone(phone *string, secret string) (*User, int) { utils.AssertNotEmptyString(phone) o := orm.NewOrm() user := User{Phone: phone} err := o.Read(&user, "Phone") if err != nil { return nil, utils.ERROR_CODE_USERS_USER_NOT_EXISTS } if utils.Secret2Password("phone:"+*phone, secret) != user.Password { return nil, utils.ERROR_CODE_TOKENS_PASSWORD_MISMATCH } for i := 0; i < DB_UNIQUE_CONFLICT_TRY; i++ { user.Token = utils.GenToken() user.UpdateAt = utils.GetTimeMillis() _, err = o.Update(&user) if err == nil { return &user, 0 } time.Sleep(1 * time.Millisecond) } beego.Warning("VerifyUser, update token fail: ", err) return nil, utils.ERROR_CODE_SYSTEM_ERROR }
// callee's duty to commit & rollback func updateUserInternal(o *orm.Ormer, user *User) int { _, err := (*o).Update(user) if err != nil { beego.Warning("UpdateUser, update user fail: ", user, err) return utils.ERROR_CODE_SYSTEM_ERROR } return 0 }
func invalidateVerification(verification *Verification, o orm.Ormer) int { verification.Expire = 0 _, err := o.Update(verification) if err == nil { return 0 } else { beego.Warning("CheckVerifyCode, Update expire fail: ", err) return utils.ERROR_CODE_SYSTEM_ERROR } }
func CreateVerification(phone string) int { o := orm.NewOrm() code := utils.GenVerifyCode() // TODO send verify code verification := Verification{Phone: phone} _, _, err := o.ReadOrCreate(&verification, "Phone") if err != nil { beego.Warning("CreateVerification, ReadOrCreate fail: ", err) return utils.ERROR_CODE_SYSTEM_ERROR } verification.Code = code verification.Expire = time.Now().Unix() + utils.VERIFY_CODE_EXPIRE_IN_SECONDS _, err = o.Update(&verification) if err != nil { beego.Warning("CreateVerification, Update fail: ", err) return utils.ERROR_CODE_SYSTEM_ERROR } return 0 }
func ldapUserAuthentication(addr, baseDN, filter, username, password, bindusername, bindpassword string, TLS bool) (success bool, userDN string, err error) { var ( sr *ldap.SearchResult ) l, err := ldap.Dial("tcp", addr) if err != nil { return } defer l.Close() // Reconnect with TLS if TLS { err = l.StartTLS(&tls.Config{InsecureSkipVerify: true}) if err != nil { beego.Warning(err) } } // First bind with a read only user err = l.Bind(bindusername, bindpassword) if err != nil { return } // Search for the given username searchRequest := ldap.NewSearchRequest( baseDN, ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false, fmt.Sprintf(filter, username), []string{"dn"}, nil, ) sr, err = l.Search(searchRequest) if err != nil { return } if len(sr.Entries) != 1 { return } userDN = sr.Entries[0].DN // Bind as the user to verify their password err = l.Bind(userDN, password) if err != nil { return } return true, userDN, err }
/* Get form error */ func IsValid(model interface{}) (err error) { valid := validation.Validation{} b, err := valid.Valid(model) if !b { for _, err := range valid.Errors { beego.Warning(err.Key, ":", err.Message) return errors.New(err.Message) // return errors.New(fmt.Sprintf("%s: %s", err.Key, err.Message)) } } return nil }
// www.example.net/about // www.example.net/?_escaped_fragment_=/about // www.example.net/some_url/?_escaped_fragment_=/about // www.example.net/about?_escaped_fragment_= func (c *MainController) Get() { // parse url host := fmt.Sprintf("http://%s", c.Ctx.Request.Host) request := c.Ctx.Input.Request.RequestURI if contain := strings.Contains(request, "_escaped_fragment_"); contain { request = c.Ctx.Input.Param(":splat") param := c.Input().Get("_escaped_fragment_") if param != "" { request = request + param } request = "/" + request } url := host + request if beego.RunMode == "dev" { beego.Warning(fmt.Sprintf("url: %s", url)) } // cache init cacheKey := m.CacheGetKey(url) bm, _ := m.Cache() bc := bm.IsExist(cacheKey) if bc { if r := bm.Get(cacheKey); r != nil { fmt.Fprint(c.Ctx.ResponseWriter, r.(string)) return } } // render b, err := exec.Command("timeout", strconv.FormatInt(int64(timeout.Seconds()), 10)+"s", phantomjs, script, url).Output() if err != nil { fmt.Fprint(c.Ctx.ResponseWriter, err.Error()) return } // replace meta tag result := string(b) meta := regexp.MustCompile(`<meta name="fragment" content="!">`).FindString(result) if meta != "" { result = strings.Replace(result, meta, "", -1) } // cache put bm.Put(cacheKey, result, cache_time) fmt.Fprint(c.Ctx.ResponseWriter, result) }
func (this *CCustomerMgr) AddCustomer(name string) { ch := make(chan *Customer) go func() { cus := &Customer{Name: name} id, err := this.myOrm.Insert(cus) if err != nil { beego.Warning(err.Error) } cus.Id = int32(id) ch <- cus }() customer := <-ch this.CustomerList = append(this.CustomerList, customer) this.CustomerMap[customer.Id] = customer }
////////////////////////////////////////////////// // DeleteMessageFromDatabase reads the users that are in the group of a user func DeleteMessageFromDatabase(userName string, messageId int64) error { o := orm.NewOrm() o.Using("default") // Using default, you can use other database u := &User{ Name: userName, } var num int64 err := o.Read(u, "Name") if err == nil { num, err = o.QueryTable("message").Filter("user", u).Filter("id", messageId).Delete() beego.Warning("Deleted", num, "entries. Id =", messageId) } if err != nil { beego.Error(err) } return err }
/////////////////////////////////// // Post func (c *LoginController) Post() { T := models.T token := c.getWebSocketsToken() var ( u models.User err error ) uf := models.UserForm{} dest := c.Ctx.Input.Query("_dest") if dest == "" { dest = "/" } if err = c.ParseForm(&uf); err == nil { beego.Warning("Login by", uf.Name, "with token", uf.Token, "and destination", dest) if token != uf.Token { err = errors.New("Token missmatch at Login. (Restart the browser ... and inform the Admin) Token1:" + token + "Token2:" + uf.Token) } else if u, err = models.AuthenticateUser(&uf); err == nil { token = c.setUserSessionData(u.Name) c.Ctx.Redirect(302, dest) return } else { err = errors.New(T["login_password_incorrect"]) } } c.Data["Error"] = err.Error() c.Data["LoginInvitation"] = T["login_invitation"] c.Data["LoginInputName"] = T["login_input_name"] c.Data["LoginPassword"] = T["login_input_password"] c.Data["LoginLoginGo"] = T["login_login_go"] c.Data["Destination"] = dest c.Data["WebSocketsToken"] = token c.TplName = "login.html" }
func CreateUserByPhone(phone *string, secret string) (*User, int) { utils.AssertNotEmptyString(phone) o := orm.NewOrm() password := utils.Secret2Password("phone:"+*phone, secret) user := User{Phone: phone, Password: password} var err error for i := 0; i < DB_UNIQUE_CONFLICT_TRY; i++ { user.Uid = utils.GenUid() user.Token = utils.GenToken() now := utils.GetTimeMillis() user.CreateAt = now user.UpdateAt = now _, err = o.Insert(&user) if err == nil { return &user, 0 } time.Sleep(1 * time.Millisecond) } beego.Warning("CreateUser fail: ", err) return nil, utils.ERROR_CODE_SYSTEM_ERROR }
func renameSourceFile(s session.Store, fileNames []string, fileType string) Data { // if user is not logged in return if s.Get("UserName") == nil { return Data{} } name := s.Get("UserName").(string) dir := beego.AppConfig.String("userdata::location") + name + "/" + fileType + "/" _, err := os.Stat(dir + "/" + fileNames[1]) if !os.IsNotExist(err) { return Data{ "Error": "file exists", } } err = os.Rename(dir+"/"+fileNames[0], dir+"/"+fileNames[1]) if err != nil { return Data{ "Error": "cannot rename file", } } // Also rename associated pngs for i := 0; i < 2; i++ { fileNames[i] = fileNames[i][:strings.LastIndex(fileNames[i], ".")] + ".png" } beego.Warning("Renaming", fileNames[0], "to", fileNames[1]) err = os.Rename(dir+"/"+fileNames[0], dir+"/"+fileNames[1]) if err != nil { return Data{ "Error": "cannot rename file", } } return Data{} }
func writeSourceFile(s session.Store, fileName string, project string, fileType string, codeFile string, timeStamp int64, Image string, alternateFile string, alternateType string, overwrite bool) Data { // if user is not logged in return if s.Get("UserName") == nil { return Data{} } T := models.T userName := s.Get("UserName").(string) if project == "/" { project = "" } //////////////////////////////////////// // Retrieve rights and users if it is a project rights := []string{} users := []string{} if project != "" { rights = models.GetProjectRightsFromDatabase(userName, project) users = models.GetProjectUsersFromDatabase(project) beego.Warning("writeSourceFile:", userName, project, rights, users) } if project != "" && !models.CheckRight(userName, project, "Write") { return Data{ "Error": "Insufficient rights for project " + project, } } var dir string if project != "" { dir = beego.AppConfig.String("userdata::location") + userName + "/" + beego.AppConfig.String("userdata::projects") + "/" + project + "/" + fileType + "/" } else { dir = beego.AppConfig.String("userdata::location") + userName + "/" + fileType + "/" } var ( file *os.File err error savedTimeStamp int64 ) filePath := dir + fileName ///////////////////////////////////////// // Check if directory is there and create if not // fileStat, err := os.Stat(filePath) if os.IsNotExist(err) { if err = os.MkdirAll(dir, os.ModePerm); err != nil { beego.Error("Cannot create directory", dir) return Data{} } } else if err != nil { beego.Error("Error while checking for directory", dir) return Data{} } ///////////////////////////////////////// // Don't overwrite file unintendedly fileStat, err = os.Stat(filePath) if !overwrite { if !os.IsNotExist(err) { return Data{ "Error": T["websockets_file_exists"], } } else if err == nil { time := fileStat.ModTime().UnixNano() / int64(time.Millisecond) // Look if the file changed on disk since last writing if time > timeStamp { return Data{ "OutdatedTimeStamp": time, } } } } ///////////////////////////////////////// // Also check if alternate file type (png, mp3) would be overwritten altSubDir := "" switch alternateType { case "png": altSubDir = beego.AppConfig.String("userdata::imagefiles") case "mp3": altSubDir = beego.AppConfig.String("userdata::soundfiles") } altDir := dir[:len(dir)-len(fileType)-1] + altSubDir + "/" altFileName := altDir + fileName[:len(fileName)-len(fileType)] + alternateType if alternateType != "" { fileStat, err = os.Stat(altFileName) if !overwrite { if !os.IsNotExist(err) { return Data{ "Error": T["websockets_file_exists"], } } } } beego.Warning("altDir:", altDir, "altFileName:", altFileName) ///////////////////////////////////////// // Create/overwrite file if file, err = os.Create(filePath); err != nil { beego.Error("Cannot create or overwrite file", filePath) return Data{} } defer file.Close() _, err = file.Write([]byte(codeFile)) //////////////////////////////////////// // Record timestamps for web app if err == nil { fileStat, _ = file.Stat() savedTimeStamp = fileStat.ModTime().UnixNano() / int64(time.Millisecond) } else { beego.Error("Cannot write to file", filePath) return Data{} } //////////////////////////////////////// // Create image file createImageFile(Image, filePath) if alternateType == "png" { createImageFile(alternateFile, altFileName) } else if alternateType == "mp3" { // create sound file } return Data{ "SavedTimeStamp": savedTimeStamp, "Rights": rights, "Users": users, } }
// callee's duty to commit & rollback func createOrUpdateUserInternal(o *orm.Ormer, user *User, authUser *utils.AuthUserInfo, logTag string, platform int) (*User, int) { if user != nil { if utils.IsLegalRestrictedStringWithLength(authUser.Nickname, utils.USER_NICKNAME_MEX_LEN) { user.Nickname = authUser.Nickname } user.Avatar = authUser.Avatar user.Gender = authUser.Gender switch platform { case utils.SNS_PLATFORM_WEIXIN: user.WeiXinNickName = authUser.Nickname case utils.SNS_PLATFORM_WEIBO: user.WeiBoNickName = authUser.Nickname case utils.SNS_PLATFORM_QQ: user.QQNickName = authUser.Nickname } var err int for i := 0; i < DB_UNIQUE_CONFLICT_TRY; i++ { user.Token = utils.GenToken() user.UpdateAt = utils.GetTimeMillis() err = updateUserInternal(o, user) if err == 0 { return user, 0 } time.Sleep(1 * time.Millisecond) } beego.Warning(logTag, err) return nil, utils.ERROR_CODE_SYSTEM_ERROR } user = &User{Gender: authUser.Gender, Avatar: authUser.Avatar} if utils.IsLegalRestrictedStringWithLength(authUser.Nickname, utils.USER_NICKNAME_MEX_LEN) { user.Nickname = authUser.Nickname } switch platform { case utils.SNS_PLATFORM_WEIXIN: user.WeiXin = &authUser.Openid user.WeiXinNickName = authUser.Nickname case utils.SNS_PLATFORM_WEIBO: user.WeiBo = &authUser.Openid user.WeiBoNickName = authUser.Nickname case utils.SNS_PLATFORM_QQ: user.QQ = &authUser.Openid user.QQNickName = authUser.Nickname } var err error for i := 0; i < DB_UNIQUE_CONFLICT_TRY; i++ { user.Uid = utils.GenUid() user.Token = utils.GenToken() now := utils.GetTimeMillis() user.CreateAt = now user.UpdateAt = now _, err = (*o).Insert(user) if err == nil { return user, 0 } time.Sleep(1 * time.Millisecond) } beego.Warning(logTag, err) return nil, utils.ERROR_CODE_SYSTEM_ERROR }
func readSourceFiles(s session.Store, fileNames []string, fileProjects []string, fileType string) Data { // if user is not logged in return if s.Get("UserName") == nil { return Data{} } name := s.Get("UserName").(string) dir := beego.AppConfig.String("userdata::location") + name + "/" codeFiles := make(map[string]SourceFile) for i := 0; i < len(fileNames); i++ { var ( file *os.File err error ) ///////////////////////////////////////// // Fetch project project := fileProjects[i] status := STATUS_OK if project != "" { _, err := fetchProject(s, project) if err != nil { switch err.Error() { case "uncommitted changes": beego.Warning("Uncommitted changes detected with project", "for user", name) status = STATUS_UNCOMMITTED } } } ///////////////////////////////////////// // Read file var fileName string if project != "" { fileName = dir + beego.AppConfig.String("userdata::projects") + "/" + project + "/" + fileType + "/" + fileNames[i] } else { fileName = dir + fileType + "/" + fileNames[i] } if file, err = os.Open(fileName); err != nil { beego.Error("Cannot open file", fileName) return Data{} } defer file.Close() fileInfo, _ := file.Stat() fileSize := fileInfo.Size() codeFile := make([]byte, fileSize) _, err = file.Read(codeFile) if err != nil { beego.Error("Read error occured.") return Data{} } rights := []string{} users := []string{} if project != "" { rights = models.GetProjectRightsFromDatabase(name, project) users = models.GetProjectUsersFromDatabase(project) } codeFiles[fileNames[i]] = SourceFile{ TimeStamp: fileInfo.ModTime().UnixNano() / int64(time.Millisecond), Code: string(codeFile), Project: project, Rights: rights, Users: users, Status: status, } } return Data{ "CodeFiles": codeFiles, } }
func (this *MyEmotionController) Post() { if !checkAccount(this.Ctx) { this.Redirect("/login", 302) return } tags := this.Input().Get("tags") eid := this.Input().Get("eid") uname := currentUser(this.Ctx) w := this.Ctx.ResponseWriter if len(eid) == 0 { //上传表情 files, err := this.GetFiles("image") if err != nil { http.Error(w, err.Error(), http.StatusNoContent) this.Redirect("/my", 302) return } for i, _ := range files { fh := files[i] f, err := fh.Open() defer f.Close() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } //读取前500字节生成MD5 b := make([]byte, 500) f.Read(b) f.Seek(0, 0) var image string var md5Name string if fh != nil { image = fh.Filename beego.Info(image) md5Name = fmt.Sprintf("%x", md5.Sum(b)) beego.Info(md5Name) } //查重 if models.CheckDuplicate(md5Name) { this.Redirect("/my", 302) beego.Warning("Duplicate image: " + image) continue } //保存到文件 //create destination file making sure the path is writeable. dst, err := os.Create("emotions/" + md5Name) defer dst.Close() if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } //copy the uploaded file to the destination file if _, err := io.Copy(dst, f); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } //保存到数据库 err = models.AddEmotion(md5Name, uname, tags) } } else { //修改表情 err := models.ModifyEmotion(eid, uname, tags) if err != nil { beego.Error(err) this.Redirect("/my", 302) return } } this.Redirect("/my", 302) }
func readDir(s session.Store, fileType string) Data { data := Data{} sourceFiles := make(map[string]SourceFile) projectNames := make([]string, 1, models.MaxProjectsPerUser) projectNames[0] = "/" userName := s.Get("UserName") // if user is not logged in return if userName == nil { return data } // First search in the main directory name := userName.(string) dir := beego.AppConfig.String("userdata::location") + name + "/" + fileType files, err := ioutil.ReadDir(dir) if os.IsNotExist(err) { beego.Warning("Directory", dir, "is not available.") } else if err != nil { beego.Error(err) return data } for _, f := range files { name := f.Name() if name[len(name)-len(fileType):] == fileType { sourceFiles[name] = SourceFile{ TimeStamp: f.ModTime().UnixNano() / int64(time.Millisecond), Project: "", } } } // Then read all projects and look into the dir of the specified filetype (e.g. pjs) dir = beego.AppConfig.String("userdata::location") + name + "/" + beego.AppConfig.String("userdata::projects") projects, err := ioutil.ReadDir(dir) if err != nil { beego.Error(err) return data } for _, p := range projects { var dir2 string if p.IsDir() == true { project := p.Name() dir2 = dir + "/" + p.Name() + "/" + fileType files, err := ioutil.ReadDir(dir2) if os.IsNotExist(err) { beego.Warning("Directory", dir2, "is not available.") } else if err != nil { beego.Error(err) return data } for _, f := range files { name := f.Name() if name[len(name)-len(fileType):] == fileType { sourceFiles[name] = SourceFile{ TimeStamp: f.ModTime().UnixNano() / int64(time.Millisecond), Project: project, } } } } } projectNames = append(projectNames, models.GetProjectsWithRightFromDatabase(name, "Write")...) data["Files"] = sourceFiles data["Projects"] = projectNames return data }
////////////////////////////////////////////////////////// // GitAddCommitPush func GitAddCommitPush(userName string, dir string, message string, firstCommit bool) error { /////////////////////////////////////////////////////////////////////// // Add // // 1 Open repository repo, err := git.OpenRepository(dir) if err != nil { beego.Error("OpenRepository - ", err) } // 2 Retrieve index index, err := repo.Index() if err != nil { beego.Error("Index - ", err) } // 3 Remember if we had conflicts before we added everything to the index indexHadConflicts := index.HasConflicts() // 4 Add everything to the index err = index.AddAll([]string{}, git.IndexAddDefault, nil) if err != nil { beego.Error("AddAll - ", err) } // 5 Write the index (so git knows about it) err = index.Write() if err != nil { beego.Error("Write - ", err) } // 6 Write the current index tree to the repo treeId, err := index.WriteTreeTo(repo) if err != nil { beego.Error("WriteTreeTo - ", err) } ///////////////////////////////////////////////////////////////////////////////////////////// // Commit // // 1 Retrieve the tree we just wrote (git's reference of it that it made in the last step) tree, err := repo.LookupTree(treeId) if err != nil { beego.Error("LookupTree - ", err) } // 2 Create a signature sig := &git.Signature{ Name: userName, Email: userName + "@" + beego.AppConfig.String("userdata::emailserver"), When: time.Now(), } // 3 Get or create remote remote, err := repo.Remotes.Lookup("origin") if err != nil { remote, err = repo.Remotes.Create("origin", repo.Path()) if err != nil { beego.Error("CreateRemote - ", err) } } // 4 Determine if this is a first commit ... if firstCommit == true { // 4a ... then create a new one _, err = repo.CreateCommit("HEAD", sig, sig, message, tree) } else { // 4b ... or retrieve current head currentBranch, err := repo.Head() if err != nil { beego.Error("Head - ", err) } // 5 Read the remote branch remoteBranch, err := repo.References.Lookup("refs/remotes/origin/master") if err != nil { beego.Error("Fetch 2 - ", err) } // 6 Retrieve current commit currentTip, err := repo.LookupCommit(currentBranch.Target()) if err != nil { beego.Error("LookupCommit - ", err) } // 7 Create a new one on top currentCommit, err := repo.CreateCommit("HEAD", sig, sig, message, tree, currentTip) if err != nil { beego.Error("CreateCommit - ", err) } //////////////////////////////////////////////////////////////////////////////////// // Merge commit (in case of -- now hopefully resolved -- conflicts) // // 1 If there were conflicts, do the merge commit if indexHadConflicts == true { // 2 Retrieve the local commit localCommit, err := repo.LookupCommit(currentCommit) if err != nil { beego.Error("Fetch 11 - ", err) } // 3 Retrieve the remote commit remoteCommit, err := repo.LookupCommit(remoteBranch.Target()) if err != nil { beego.Error("Fetch 12 - ", err) } // 4 Create a new one repo.CreateCommit("HEAD", sig, sig, "Merge commit", tree, localCommit, remoteCommit) // 5 Clean up repo.StateCleanup() } /////////////////////////////////////////////////////////////////////////////////// // Pull (Fetch and Merge) // // 1 Fetch it err = remote.Fetch([]string{}, nil, "") if err != nil { beego.Error("Fetch 1 - ", err) } // 2 Read the remote branch remote, err = repo.Remotes.Lookup("origin") remoteBranch, err = repo.References.Lookup("refs/remotes/origin/master") if err != nil { beego.Error("Fetch 2 - ", err) } // 3 Perform an annotated commit annotatedCommit, err := repo.AnnotatedCommitFromRef(remoteBranch) if err != nil { beego.Error("Fetch 3 - ", err) } // 4 Do the merge analysis mergeHeads := make([]*git.AnnotatedCommit, 1) mergeHeads[0] = annotatedCommit analysis, _, err := repo.MergeAnalysis(mergeHeads) if err != nil { beego.Error("Fetch 4 - ", err) } // 5 Check if something happend if analysis&git.MergeAnalysisUpToDate == 0 && analysis&git.MergeAnalysisNormal != 0 { // 6 Yes! First just merge changes if err := repo.Merge([]*git.AnnotatedCommit{annotatedCommit}, nil, nil); err != nil { beego.Error("Fetch 5 - ", err) } // 7 Retrieve the index after that treatment index, err := repo.Index() if err != nil { beego.Error("Fetch 6 - ", err) } // 8 Check for conflicts if index.HasConflicts() { beego.Warning("Conflicts occured while merging project repository in", dir, "(User:"******")") // 8a There are not automaticly solvable conflicts ... give them back to the user err = index.Write() if err != nil { beego.Error("Write - ", err) } return errors.New("Conflicts") } // 9 Write the new tree treeId, err := index.WriteTree() if err != nil { beego.Error("Fetch 9 - ", err) } // 10 Retrieve the new tree tree, err := repo.LookupTree(treeId) if err != nil { beego.Error("Fetch 10 - ", err) } // 11 Retrieve the local commit localCommit, err := repo.LookupCommit(currentCommit) if err != nil { beego.Error("Fetch 11 - ", err) } // 12 Retrieve the remote commit remoteCommit, err := repo.LookupCommit(remoteBranch.Target()) if err != nil { beego.Error("Fetch 12 - ", err) } // 13 Create a new one repo.CreateCommit("HEAD", sig, sig, "Merge commit", tree, localCommit, remoteCommit) // 14 Clean up repo.StateCleanup() } else if analysis&git.MergeAnalysisFastForward != 0 { beego.Warning("Git Merge: Fast Forward") // 15 Get remote tree remoteTree, err := repo.LookupTree(remoteBranch.Target()) if err != nil { return err } // 16 Checkout if err := repo.CheckoutTree(remoteTree, nil); err != nil { return err } // 17 Get current branch branch, err := repo.References.Lookup("refs/heads/master") if err != nil { return err } // 18 Point branch to the object branch.SetTarget(remoteBranch.Target(), "") if _, err := currentBranch.SetTarget(remoteBranch.Target(), ""); err != nil { return err } } } ////////////////////////////////////////////////////////////////////////////////////////////////////// // Push err = remote.Push([]string{"refs/heads/master"}, nil) if err != nil { beego.Error("Push - ", err) } return err }