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  }