github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/third/kmgGit/FakeSubmodule.go (about) 1 package kmgGit 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 8 "github.com/bronze1man/kmg/encoding/kmgJson" 9 "github.com/bronze1man/kmg/kmgFile" 10 "github.com/bronze1man/kmg/kmgRand" 11 ) 12 13 type SubRepositoryInfo struct { 14 RemoteUrl string 15 CommitId string 16 } 17 18 //TODO 修复bug: A commit了一个子项目,B update这个子项目 ,A 删除了一种的一个子项目,并且commit到远程分支,B update了这个子项目,此时 B会加入这个子项目的真submodule 19 //TODO 修复bug: origin/master的实时性不强的问题. 20 //TODO 修复bug时,写测试. 21 22 //把当前项目里面的所有的子项目都变成伪submodule,并且保存版本信息到.gitFakeSubmodule 中 23 func (repo *Repository) MustFakeSubmoduleCommit() { 24 //把当前目录下面的所有叫.git的目录都翻出来 25 rootPath := repo.gitPath 26 SubmoduleList := map[string]SubRepositoryInfo{} 27 err := filepath.Walk(rootPath, func(path string, info os.FileInfo, err error) error { 28 if filepath.Base(path) != ".git" { 29 return nil 30 } 31 path = filepath.Dir(path) 32 if path == rootPath { 33 return nil 34 } 35 relPath, err := filepath.Rel(rootPath, path) 36 if err != nil { 37 panic(err) 38 } 39 ret := repo.MustFakeSubmoduleAdd(relPath) 40 if !ret { 41 return nil 42 } 43 //记录版本号 44 subRepo := MustGetRepositoryFromPath(path) 45 commitId := subRepo.MustGetHeadCommitId() 46 if !subRepo.MustIsInParent("origin/master", commitId) { 47 fmt.Printf("warning: [%s] HEAD is not in origin/master\n", relPath) 48 } 49 SubmoduleList[relPath] = SubRepositoryInfo{ 50 RemoteUrl: subRepo.MustGetRemoteUrl("origin"), 51 CommitId: commitId, 52 } 53 return nil 54 }) 55 if err != nil { 56 panic(err) 57 } 58 kmgJson.MustWriteFileIndent(filepath.Join(rootPath, ".gitFakeSubmodule"), SubmoduleList) 59 return 60 } 61 62 //从 .gitFakeSubmodule 中还原旧的fakeSubmoudle,并且将所有子项目都切换到该文件里面写的分支(使用reset切分支,保证不掉数据) 63 func (repo *Repository) MustFakeSubmoduleUpdate() { 64 rootPath := repo.gitPath 65 SubmoduleList := map[string]SubRepositoryInfo{} 66 kmgJson.MustReadFile(filepath.Join(rootPath, ".gitFakeSubmodule"), &SubmoduleList) 67 for repoPath, SubmoduleInfo := range SubmoduleList { 68 repoRealPath := filepath.Join(rootPath, repoPath) 69 //子项目存在? 70 if !MustIsRepositoryAtPath(repoRealPath) { 71 tmpPath := filepath.Join(repoRealPath, kmgRand.MustCryptoRandToHex(8)) 72 kmgFile.MustMkdir(tmpPath) 73 MustGitClone(SubmoduleInfo.RemoteUrl, tmpPath) 74 kmgFile.MustRename(filepath.Join(tmpPath, ".git"), filepath.Join(repoRealPath, ".git")) 75 kmgFile.MustDelete(tmpPath) 76 } 77 //子项目的远程路径正确? 78 subRepo := MustGetRepositoryFromPath(repoRealPath) 79 if subRepo.MustGetRemoteUrl("origin") != SubmoduleInfo.RemoteUrl { 80 subRepo.MustSetRemoteUrl("origin", SubmoduleInfo.RemoteUrl) 81 } 82 //子项目的版本号正确? 83 if subRepo.MustGetHeadCommitId() != SubmoduleInfo.CommitId { 84 subRepo.MustResetToCommitId(SubmoduleInfo.CommitId) 85 } 86 } 87 } 88 89 //这个函数返回 经过处理后该路径是否是一个伪submodule 90 // 请调用者保证这个path里面有.git文件夹 91 func (repo *Repository) MustFakeSubmoduleAdd(path string) bool { 92 //已经是伪submodule 93 if repo.MustHasFilesInDirInIndex(path) { 94 return true 95 } 96 //1.被忽略,此处也忽略,什么也不做 97 if repo.MustIsFileIgnore(path) { 98 return false 99 } 100 //2.是真submodule 101 if repo.MustIsFileInIndex(path) { 102 repo.MustIndexRemoveByPath(path) 103 } 104 //3.没有加入Index里面 105 subrepo := MustGetRepositoryFromPath(filepath.Join(repo.gitPath, path)) 106 if subrepo.gitPath == repo.gitPath { 107 panic("[MustFakeSubmoduleAdd] input path do not have .git file") 108 } 109 fileList := subrepo.MustGetIndexFileList() 110 if len(fileList) == 0 { 111 panic("[MustFakeSubmoduleAdd] submodule do not have any file in index") 112 } 113 114 //加入该submodule里面任意一个文件(速度快) 115 for _, file := range fileList { 116 repo.MustIndexAddFile(filepath.Join(path, file)) 117 return true 118 } 119 return true 120 }