5.文件移植性

Posted on Posted in 4.高级主题

文件移植性

幸运的是,对于许多在不同操作系统下工作的用户,Subversion命令行程序的行为方式几乎完全一致,如果你知道在一个平台上如何运行svn,你也就学会了在其他平台上运行。

然而,这一点在本软件的其他几类地方或Subversion保持的实际文件并不一定都是正确的。例如,在一个Windows系统,“文本文件”的定义与Linux环境下的类似,但是也有区别—行结束的字符串并不相同。当然也有其他的区别,Unix平台支持(Subversion也支持)符号链;Windows不知吃,Unix使用文件系统执行位来检测可执行性;而Windows使用文件扩展名。

因为Subversion不是要将世界上的所有此类事情统一起来,所以我们最好是尽可能让我们在多个计算机和操作系统上使用版本化文件和目录时能够更简单,本节描述了Subversion是如何做的。

文件内容类型

Subversion同很多应用一样利用多用途网际邮件扩展(MIME)内容类型,svn:mime-type属性为Subversion的许多目的服务,除了保存一个文件的MIME分类以外,这个svn:mime-type属性值也描述了一些Subversion自己使用的行为特性。

识别文件类型

大多数现代操作系统通过文件名的扩展名推断文件的类型和格式,例如,以.txt为后缀的文件通常被认为是可读的,不需要通过复杂的解码处理就可以被阅读。对于后缀名为.png文件,则被认为是Portable Network Graphics类型—不是可读的格式,只能通过识别PNG格式并且可以将信息转化为光栅的软件使用。

不幸的是,一些扩展名已经随时间改变了意义。当个人电脑第一次出现时,一个叫做README.DOC的文件一定是一个纯文本文件了,就像现在的.txt文件。但是在九十年代中期,你可以打赌这个文件已经不是文本文件,而变成了微软的私有的、不可读的Word文档格式。但是这个变化不是一夜完成的—在一段时间里一定会有用户在看到一个.DOC时感到困惑。[11]

计算机网络的普及导致对于文件名和其关联内容的更多混淆,当信息存放在网络上并由服务器脚本动态生成时,会没有文件名。Web服务器,需要使用其他方式告诉浏览器它们所请求内容的信息,这样浏览器才能智能的根据信息作一些事情,或者是使用注册的程序显示数据,或者是提示用户将文件下载到某个地方。

最终,一个描述数据流内容的标准出现了。1996年,5个描述MIME的RFC中的第一个RFC2045发布了,这个RFC描述了媒体类型和子类型概念,并且提出了表示这些类型的推荐语法。现在,MIME媒体类型—MIME类型已经广泛应用在电邮应用,Web服务器和其他软件,成为了防止文件内容混淆的标准机制。

举个例子,一个好处就是Subversion在更新时通常可以提供基于上下文的行为基础的合并,如果一个文件svn:mime-type属性设置为非文本的MIME类型(通常是那些不是text/开头的类型,但也有例外),Subversion会假定这个文件保存了二进制内容—也就是不可读的数据。一个好处就是Subversion通常在更新工作拷贝时提供了一个前后相关的以行为基础的修改合并,但是对于二进制数据文件,没有“行”的概念,所以对这些文件,Subversion不会在更新时尝试执行合并操作,相反,任何时候你在本地已经修改的一个二进制文件有了更新,你的文件扩展名会修改为.orig,然后Subversion保存一个新的工作拷贝文件来保存更新时得到的修改,但原来的文件名已经不是你自己的本地修改。这个行为模式是用来保护用户在对不可文本合并的文件尝试执行文本的合并时失败的情形。

另外,如果设置了svn:mime-type属性,Subversion的Apache模块会使用这个值来在HTTP头里输入Content-type:,这给了web浏览器如何显示版本库的一个文件提供了至关重要的线索。

文件的可执行性

在多数操作系统,执行一个文件或命令的能力是由执行位管理的,这些位缺省是关闭的,必须由用户根据需要显式的指定,但是记住应该为哪些检出的文件设置可执行位会是一件很麻烦的事情,所以Subversion提供了svn:executable这个属性来保持打开执行位,在工作拷贝得到这些文件时设置执行位。

这个属性对于没有可执行权限位的文件系统无效,如FAT32和NTFS。 [12]也就是说,尽管它没有定义的值,在设置这个属性时,Subversion会强制它的值为*,最后,这个属性只对文件有效,目录无效。

行结束字符串

除非使用版本化文件的svn:mime-type属性注明,Subversion会假定这个文件保存了可读的数据,一般来讲,Subversion只使用这些信息来判断一个文件是否可以用上下文区别的报告,否则,对Subversion来说只是字节。

这意味着缺省情况下,Subversion不会关注任何行结束标记(end-of-line,EOL),不幸的是不同的操作系统在文本文件使用不同的行结束标志,举个例子,Windows平台下的A编辑工具使用一对ASCII控制字符—回车(CR)和一个换行(LF),而Unix软件,只使用一个LF来表示一个行的结束。

并不是所有操作系统的工具准备好了理解与本地行结束样式不一样的行结束格式,一个常见的结果是Unix程序会把Windows文件中的CR当作一个不同的字符(通常表现为^M),而Windows程序会把Unix文件合并为一个非常大的行,因为没有发现标志行结束的回车加换行(或者是CRLF)字符。

对外来EOL标志的敏感会让在多种操作系统分享文件的人们感到沮丧,例如,考虑有一个源代码文件,开发者会在Windows和Unix系统上编辑这个文件,如果所有的用户使用的工具可以展示文件的行结束,那就没有问题了。

但实践中,许多常用的工具不会正确的读取外来的EOL标志,或者只是在保存文件时将文件的行结束符转化为本地的样式,如果是前者,他需要一个外部的转化工具(如dos2unix,或是他的伴侣unix2dos)来准备需要编辑的文件。后一种情况不需要额外的准备工作,两种方法都会造成文件会与原来的文件在每一行上都不一样!在提交之前,用户有两个选择,或者选择用一个转化工具恢复文件的行结束样式,或者是简单的提交文件—包含新的EOL标志。

这个情景的结局看起来像是要浪费时间对提交的文件作不必要的修改,浪费时间是痛苦的,但是如果提交修改了文件的每一行,判断文件修改了哪一行会是一件复杂的工作,bug在哪一行修正的?哪一行导致了语法错误?

这个问题的解决方案是svn:eol-style属性,当这个属性设置为一个正确的值时,Subversion使用它来判断针对行结束样式执行何种特殊的操作,而不会随着多种操作系统的每次提交而发生剧烈变化,正确的值有:

  •              native

  • 这会导致保存EOL标志的文件使用Subversion运行的操作系统的本地编码,换句话说,如果一个Windows用户取出一个工作拷贝包含的文件设置native的属性为svn:eol-style,这个文件会使用CRLF的EOL标志,一个Unix用户取出相同的文件会看到他的文件使用LF的EOL标志。

    注意Subversion实际上使用LF的EOL标志,而不会考略操作系统,尽管这对用户来说是透明的。

  •              CRLF

  • 这会导致这个文件使用CRLF序列作为EOL标志,不管使用何种操作系统。

  •              LF

  • 这会导致文件使用LF字符作为EOL标志,不管使用何种操作系统。

  •              CR

  • 这会导致文件使用CR字符作为EOL标志,不管使用何种操作系统。这种行结束样式不是很常见,它用在一些老的苹果机(Subversion不会运行的机器上)上。


[11] 你认为那样过于粗狂?在同一个时代里,WordPerfect也使用.DOC作为它们私有文件格式的扩展名!

[12] Windows文件系统使用文件扩展名(如.EXE、.BAT和.COM)来标示可执行文件。