文章

vscode-git插件代码研究

vscode-git插件代码研究

  1. 所有的git命令都是通过stream方法调用,用于记录所有git操作相关的命令记录,以及时间消耗
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    stream(cwd: string, args: string[], options: SpawnOptions = {}): cp.ChildProcess {
         options = assign({ cwd }, options || {});
         const child = this.spawn(args, options);
    
         if (options.log !== false) {
             const startTime = Date.now();
             child.on('exit', (_) => {
                 this.log(`> git ${args.join(' ')} [${Date.now() - startTime}ms]${child.killed ? ' (cancelled)' : ''}\n`);
             });
         }
    
         return child;
     }
    
  2. 日志输出通过eventEmitter,在内部打印日志,在最上层输出日志
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    // 最上层
    const onOutput = (str: string) => {
         const lines = str.split(/\r?\n/mg);
    
         while (/^\s*$/.test(lines[lines.length - 1])) {
             lines.pop();
         }
    
         logger.appendLine(lines.join('\n'));
     };
     git.onOutput.addListener('log', onOutput);
     disposables.push(toDisposable(() => git.onOutput.removeListener('log', onOutput)));
    // 内部定义output 
    private _onOutput = new EventEmitter();
    get onOutput(): EventEmitter { return this._onOutput; }
    // 内部使用log
    private log(output: string): void {
     this._onOutput.emit('log', output);
    }
    this.log(`> git ${args.join(' ')} [${Date.now() - startTime}ms]${child.killed ? ' (cancelled)' : ''}\n`);
    
  3. 在执行git相关命令后,返回的结果中必定包含GitErrorCode,建立错误码机制,以了解到底是因为什么导致Git错误
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    function getGitErrorCode(stderr: string): string | undefined {
     if (/Another git process seems to be running in this repository|If no other git process is currently running/.test(stderr)) {
         return GitErrorCodes.RepositoryIsLocked;
     } else if (/Authentication failed/i.test(stderr)) {
         return GitErrorCodes.AuthenticationFailed;
     } else if (/Not a git repository/i.test(stderr)) {
         return GitErrorCodes.NotAGitRepository;
     } else if (/bad config file/.test(stderr)) {
         return GitErrorCodes.BadConfigFile;
     } else if (/cannot make pipe for command substitution|cannot create standard input pipe/.test(stderr)) {
         return GitErrorCodes.CantCreatePipe;
     } else if (/Repository not found/.test(stderr)) {
         return GitErrorCodes.RepositoryNotFound;
     } else if (/unable to access/.test(stderr)) {
         return GitErrorCodes.CantAccessRemote;
     } else if (/branch '.+' is not fully merged/.test(stderr)) {
         return GitErrorCodes.BranchNotFullyMerged;
     } else if (/Couldn\'t find remote ref/.test(stderr)) {
         return GitErrorCodes.NoRemoteReference;
     } else if (/A branch named '.+' already exists/.test(stderr)) {
         return GitErrorCodes.BranchAlreadyExists;
     } else if (/'.+' is not a valid branch name/.test(stderr)) {
         return GitErrorCodes.InvalidBranchName;
     } else if (/Please,? commit your changes or stash them/.test(stderr)) {
         return GitErrorCodes.DirtyWorkTree;
     }
    
     return undefined;
    }
    
  4. assign函数,合并多个对象的值,如:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    export function assign<T>(destination: T, ...sources: any[]): T {
     for (const source of sources) {
         Object.keys(source).forEach(key => (destination as any)[key] = source[key]);
     }
    
     return destination;
    }
    options.env = assign({}, process.env, this.env, options.env || {}, {
             VSCODE_GIT_COMMAND: args[0],
             LC_ALL: 'en_US.UTF-8',
             LANG: 'en_US.UTF-8',
             GIT_PAGER: 'cat'
         });
    
  5. 净化windows路径,将开头的大小变为小写 ```typescript function sanitizePath(path: string): string {     return path.replace(/^([a-z]):\/i, (_, letter) => ${letter.toUpperCase()}:\\);

} ```

本文由作者按照 CC BY 4.0 进行授权