Xudifsd Rational life

Git源码阅读——文件路径

2011-10-05
xudifsd
git

最开始在学习git用法的时候就听说了git不像其他版本管理软件(subversion)把版本信息分别放在各个子目录,而是将整个版本信息放在项目的根目录,当时就觉得这种实现似乎很有意思,但是却不知道如何实现这一点,因为每次运行git add等命令时都有可能在任意子目录。唯一能想到的方法就是绝对路径:所有版本的文件的路径都使用绝对路径来表示,但是这样一来将项目的目录进行移动或者分布式开发就有问题,而且使用od(1)来查看git的index文件也发现存的是相对路径而不是绝对路径。

git的实现

在源代码中就可以找到实现原理:几乎所有的git命令都会在启动时调用setup_git_directory,这是git的内部API,函数原型在setup.c中,这个函数就负责检查git环境并统一所有的文件路径:它尝试调用access(2)来判断该目录是否是git项目的根目录,如果不是则调用chdir(2)切换工作目录到父亲目录,如此循环直到到达根目录或者到达git项目根目录,如果成功到达项目根目录该API会返回从git根目录到之前工作目录的prefix,之后所有的对路径的操作就可以用prefix和执行命令时的相对路径来进行,git也提供了进行这样操作的API:prefix_path,这个函数负责去掉命令行参数路径中的.和..,并返回正确的路径。通过将路径统一成相对项目根目录的形式可以减轻对路径处理的工作量,所有上层命令只需在程序开始时调用setup_git_directory取得prefix,在操作路径时调用prefix_path,就能正确处理路径问题了。

Linux环境中对路径的处理

《APUE》可以得知所有的进程都有工作目录,所有的相对路径的操作都会基于工作目录,而chdir(2)可以让进程在不同的工作目录中进行切换,由内核负责保存进程的工作路径,想要取得当前工作路径只要使用getcwd(2)即可,但是需要注意的是工作目录是进程的属性,任何在子进程中修改的属性父进程都无法获得,所以在使用gdb进行调试时不可能使用getcwd来得到调试项目的工作路径的,因为调试项目是gdb的子进程。还有一点需要注意的是PWD环境变量,git在切换目录之后不会修改PWD环境变量,似乎也没有哪个应用程序会修改这个变量,这种环境变量似乎只是shell为了给shell脚本提供的,在应用程序中这样的变量是靠不住的。


上一篇 缓存的威力

Comments

Content