isomorphic-git 实现`git diff`功能(官方无diff)

在使用的过程中,发现isomorphic-git库没有提供diff 功能,那么我们可以自己实现一下

首先通过使用 git.status() 检查文件的状态,方便后面 diff 的时候,对增加删除修改进行差异化的处理。

根据文件的不同状态,执行相应的操作。如果文件是新增的,则直接将当前版本的文件内容显示出来。如果文件被删除,则查找最近一次修改该文件的提交记录,读取提交时的文件版本,并将其显示出来。如果文件被修改,则查找最近一次修改该文件的提交记录,读取提交时的文件版本和当前版本,生成文件的差异,并将差异部分高亮显示。

其中,diff 用到了第三方库diffdiff - npm

以下是完整的代码:

const fs = require('fs');
const path = require('path');
const git = require('isomorphic-git');
const diff = require('diff');

// 文件状态枚举类型
const FileStatus = {
  NEW: 'new',
  DELETED: 'deleted',
  MODIFIED: 'modified',
};

async function getGitDiff(repoPath, fileName) {
  let fileStatus = null;

  try {
    const status = await git.status({
      fs,
      dir: repoPath,
      filepath: fileName,
    });

    if (status.includes("added")) {
      fileStatus = FileStatus.NEW;
    } else if (status.includes("deleted")) {
      fileStatus = FileStatus.DELETED;
    } else {
      fileStatus = FileStatus.MODIFIED;
    }
  } catch (err) {
    if (err instanceof git.errors.NotFoundError) {
      fileStatus = FileStatus.NEW;
    } else {
      throw err;
    }
  }

  const currentBlob = fs.readFileSync(path.join(repoPath, fileName), 'utf8');
  let htmlDiff = '';

  if (fileStatus === FileStatus.NEW) {
    htmlDiff = `<pre>${JSON.stringify(currentBlob)}</pre>`;
  } else if (fileStatus === FileStatus.DELETED) {
    const commits = await git.log({
      fs,
      dir: repoPath,
      filepath: fileName,
    });

    if (commits.length > 0) {
      const { blob: committedBlob } = await git.readBlob({
        fs,
        dir: repoPath,
        filepath: fileName,
        oid: commits[0].oid,
      });

      const committedBlobStr = committedBlob.toString('utf-8');

      htmlDiff = `<pre>${JSON.stringify(committedBlobStr)}</pre>`;
    } else {
      htmlDiff = 'No changes to display.';
    }
  } else if (fileStatus === FileStatus.MODIFIED) {
    const commits = await git.log({
      fs,
      dir: repoPath,
      filepath: fileName,
    });

    if (commits.length > 0) {
      const { blob: committedBlob } = await git.readBlob({
        fs,
        dir: repoPath,
        filepath: fileName,
        oid: commits[0].oid,
      });

      const committedBlobStr = committedBlob.toString('utf-8');

      const diffResult = diff.diffLines(committedBlobStr, currentBlob);

      for (const part of diffResult) {
        if (part.added) {
          htmlDiff += `<span class="added">${part.value}</span>`;
        } else if (part.removed) {
          htmlDiff += `<span class="removed">${part.value}</span>`;
        } else {
          htmlDiff += part.value;
        }
      }
    } else {
      htmlDiff = 'No changes to display.';
    }
  }

  return htmlDiff;
}

// 测试函数
getGitDiff('your/project/pat','test.js')
  .then(htmlDiff => console.log(htmlDiff))
  .catch(err =&gt; console.error(err));</pre>
 

已发布

分类

作者:

标签

评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注