Git是否有任何本地方式来规范化(解析)符号链接,比如readlink -f?

时间:2014-10-15 07:48:09

标签: git

readlink -f,根据其手册页:

"通过递归地跟随给定名称的每个组件中的每个符号链接来规范化[s];除了最后一个组件之外的所有组件都必须存在"

我想要一个等同于" readlink -f"对于Git。换句话说,这是一种在存储库中给定提交的路径中跟踪每个符号链接的方法,最后是规范版本的路径。

我已经编写了我自己的函数(如下所示),但我想知道Git是否具有执行相同操作的本机功能。并且,如果它没有,也许值得考虑在新版本的Git中包含相同的功能。感谢。

SYMLINK_FILE_TYPE_OCTAL="12"
MAX_SYMLINK_COUNT=10

git-is-symlink() {
  local commit="$1"
  local dir="$2"
  local base="$3"
  git ls-tree "${commit}:$dir" "$base" | grep -q -P "^$SYMLINK_FILE_TYPE_OCTAL"
}

git-get-symlink-target() {
  local commit="$1"
  local dir="$2"
  local base="$3"

  if test -z "$dir"; then
    local path="$base"
  else
    local path="$dir/$base"
  fi
  git cat-file blob "$commit:$path"
}

git-resolve-path-recursive() {
  local commit="$1"
  local resolved_prefix="$2"
  local segment_to_be_resolved="$3"
  local unresolved_suffix="$4"
  local symlink_count="$5"

  if test -z "$segment_to_be_resolved" && test -z "$unresolved_suffix"; then
    echo "$resolved_prefix"
    return
  fi

  if test "$symlink_count" -gt "$MAX_SYMLINK_COUNT"; then
    echo "Exceeded symlink count of $MAX_SYMLINK_COUNT on '$prefix' '$segment_to_be_resolved'" >&2
    exit 1
  fi

  if test -n "$segment_to_be_resolved" && git-is-symlink "$commit" "$resolved_prefix" "$segment_to_be_resolved"; then
    local symlink_target="$(git-get-symlink-target "$commit" "$resolved_prefix" "$segment_to_be_resolved")"
    git-resolve-path-recursive "$commit" "$resolved_prefix" "$symlink_target" "$unresolved_suffix" $((++symlink_count))
  else
    if test -z "$resolved_prefix"; then
      local new_resolved_prefix="$segment_to_be_resolved"
    else
      local new_resolved_prefix="$resolved_prefix/$segment_to_be_resolved"
    fi
    local new_segment_to_be_resolved="$(echo "$unresolved_suffix" | cut -d / -f 1)"
    local new_unresolved_suffix="$(echo "$unresolved_suffix" | cut -s -d / -f 2-)"
    git-resolve-path-recursive "$commit" "$new_resolved_prefix" "$new_segment_to_be_resolved" "$new_unresolved_suffix" 0
  fi
}

## Main entry point
## USAGE: git-resolve-path COMMIT PATH
git-resolve-path() {
  local commit="$1"
  local path="$2"
  git-resolve-path-recursive "$commit" "" "" "$path" 0
}

使用示例:

> mkdir -p targetdir
> ln -s targetdir linkdir
> touch targetdir/targetfile
> ln -s targetfile targetdir/linkfile
> git add targetdir linkdir targetdir/targetfile targetdir/linkfile
> git commit -m "Add files"
> git-resolve-path HEAD linkdir/linkfile
targetdir/targetfile

0 个答案:

没有答案