此文本正在进行中,内容可能会发生很大变化,可能无法准确描述 Apache™ Subversion® 软件的任何已发布版本。将此页面添加书签或以其他方式将其推荐给其他人可能不是一个明智的选择。请访问 http://svnbooks.subversion.org.cn/ 以获取本书的稳定版本。

属性

我们已经详细介绍了 Subversion 如何在其存储库中存储和检索文件的各种版本。整章都致力于由该工具提供的这一最基本的功能。如果版本控制支持到此为止,从版本控制的角度来看,Subversion 仍然是完整的。

但它并没有就此止步。

除了对目录和文件进行版本控制外,Subversion 还提供接口用于在您的每个版本控制的目录和文件上添加、修改和删除版本控制的元数据。我们将此元数据称为 属性,可以将其视为将属性名称映射到附加到工作副本中每个项目上的任意值的双列表格。一般来说,属性的名称和值可以是您想要的任何内容,但名称必须仅包含 ASCII 字符。这些属性最棒的地方在于,它们也与文件的文本内容一样具有版本控制。您可以修改、提交和恢复属性更改,就像修改文件内容一样容易。并且发送和接收属性更改是您典型提交和更新操作的一部分,您不必更改基本流程来适应它们。

[Note] 注意

Subversion 保留了名称以 svn: 开头的属性集作为其自身属性。虽然目前使用的此类属性很少,但您应该避免为自己的需求创建名称以该前缀开头的自定义属性。否则,您将冒着 Subversion 的未来版本将为具有相同名称但可能具有完全不同解释的属性驱动的功能或行为增加支持的风险。

属性也会在 Subversion 的其他地方出现。正如文件和目录可能具有附加到它们上的任意属性名称和值一样,每个修订本身也可能具有附加到它上的任意属性。相同的约束适用 - 人类可读的名称和任何你想要的二进制值。主要区别在于修订属性没有版本控制。换句话说,如果您更改了修订属性的值或将其删除,则在 Subversion 功能范围内无法恢复以前的值。

Subversion 对属性的使用没有特定策略。它只要求您不要使用以前缀 svn: 开头的属性名称,因为这是它为自身使用保留的命名空间。实际上,Subversion 使用属性,包括版本控制和未版本控制的属性。某些版本控制属性在文件和目录中找到时具有特殊含义或效果,或者它们包含有关找到它们的修订版本的特定信息。某些修订属性是由 Subversion 的提交过程自动附加到修订版本上的,它们包含有关修订版本的信息。大多数这些属性在本节或其他章节中作为与之相关的更一般主题的一部分被提及。有关 Subversion 预定义属性的完整列表,请参见 名为“Subversion 保留的属性”的部分。

[Note] 注意

虽然 Subversion 会自动将属性 (svn:datesvn:authorsvn:log 等等) 附加到修订版本,但它不会 事后 假设这些属性的存在,您或用于与您的存储库交互的工具也不应该这样做。修订属性可以通过编程方式或通过客户端(如果存储库挂钩允许)删除,而不会损害 Subversion 的功能。因此,在编写操作 Subversion 存储库数据的脚本时,不要错误地假设任何特定修订属性存在于修订版本上。

在本节中,我们将研究属性支持对 Subversion 用户和 Subversion 本身的实用性。您将了解与属性相关的 svn 子命令以及属性修改如何影响您的正常 Subversion 工作流程。

为什么要使用属性?

正如 Subversion 使用属性来存储有关其包含的文件、目录和修订版本的信息一样,您也可能会发现属性具有类似的用途。您可能会发现将自定义元数据挂在版本控制数据附近很有用。

假设您想设计一个托管大量数字照片并使用标题和日期戳显示它们的网站。现在,您的照片集在不断变化,因此您希望尽可能自动化此网站。这些照片可能非常大,因此,正如这种类型的网站通常所做的那样,您希望为您的网站访问者提供更小的缩略图。

现在,您可以使用传统文件获得此功能。也就是说,您可以在一个目录中并排放置您的 image123.jpg 和一个 image123-thumbnail.jpg。或者,如果您想保持文件名相同,您可能将缩略图放在不同的目录中,例如 thumbnails/image123.jpg。您还可以以类似的方式存储您的标题和日期戳,同样将其与原始图像文件分开。但这里的问题是,您的文件集合会随着添加到网站的每张新照片而增加。

现在考虑以利用 Subversion 文件属性的方式部署的同一网站。想象一下,您有一个单个图像文件 image123.jpg,并在该文件上设置了名为 captiondatestamp,甚至 thumbnail 的属性。现在您的工作副本目录看起来更易于管理 - 事实上,对于普通浏览器来说,它看起来只包含图像文件。但是您的自动化脚本了解得更多。他们知道他们可以使用 svn(或者更好的是,他们可以使用 Subversion 语言绑定 - 请参阅 名为“使用 API”的部分)来挖掘您的网站显示所需的信息,而无需读取索引文件或进行路径操作游戏。

[Note] 注意

虽然 Subversion 对您用于属性的名称和值施加很少的限制,但它并非旨在以最佳方式在给定文件或目录上携带大型属性值或大型属性集。Subversion 通常同时将与单个项目相关联的所有属性名称和值保存在内存中,这会导致在使用极大的属性集时出现不利性能或操作失败。

自定义修订属性也经常使用。一种常见的用例是其值包含与修订相关的错误跟踪器 ID 的属性,可能是因为该修订中进行的更改修复了该跟踪器问题中的错误,该错误具有该 ID。其他用途包括在修订版本上挂上更友好的名称 - 记住修订版本 1935 是一个经过全面测试的修订版本可能很困难。但是,如果在该修订版本上有一个名为 test-results 的属性,其值为 all passing,那么这是一个有意义的信息。Subversion 允许您通过 svn commit 命令的 --with-revprop 选项轻松地执行此操作。

$ svn commit -m "Fix up the last remaining known regression bug." \
             --with-revprop "test-results=all passing"
Sending        lib/crit_bits.c
Transmitting file data .
Committed revision 912.
$

操作属性

svn 程序提供了多种方法来添加或修改文件和目录属性。对于具有简短、人类可读值的属性,添加新属性最简单的方法可能是指定属性名称和值在 svn propset 子命令的命令行上。

$ svn propset copyright '(c) 2006 Red-Bean Software' calc/button.c
property 'copyright' set on 'calc/button.c'
$

但是,我们一直在宣传 Subversion 为您的属性值提供的灵活性。如果您打算使用多行文本甚至二进制属性值,您可能不希望在命令行上提供该值。因此,svn propset 子命令接受一个 --file (-F) 选项,用于指定包含新属性值的 文件的名称。

$ svn propset license -F /path/to/LICENSE calc/button.c
property 'license' set on 'calc/button.c'
$

您用于属性的名称有一些限制。属性名称必须以字母、冒号 (:) 或下划线 (_) 开头;在此之后,您还可以使用数字、连字符 (-) 和句点 (.)。[13]

除了 propset 命令外,svn 程序还提供了 propedit 命令。该命令使用配置的编辑器程序(参见 名为“通用配置”的部分)来添加或修改属性。运行该命令时,svn 会在包含属性当前值(或为空,如果您要添加新属性)的临时文件上调用您的编辑器程序。然后,您只需在编辑器程序中修改该值,直到它代表您希望为该属性存储的新值,保存临时文件,然后退出编辑器程序。如果 Subversion 检测到您实际更改了属性的现有值,它将接受该值为新的属性值。如果您退出编辑器而没有进行任何更改,则不会进行任何属性修改。

$ svn propedit copyright calc/button.c  ### exit the editor without changes
No changes to property 'copyright' on 'calc/button.c'
$

需要注意的是,与其他 svn 子命令一样,与属性相关的子命令可以一次作用于多个路径。这使您能够使用单个命令修改整组文件上的属性。例如,我们可以执行以下操作

$ svn propset copyright '(c) 2006 Red-Bean Software' calc/*
property 'copyright' set on 'calc/Makefile'
property 'copyright' set on 'calc/button.c'
property 'copyright' set on 'calc/integer.c'
…
$

如果您不能轻松地获得存储的属性值,那么所有这些属性添加和编辑实际上并没有什么用。因此,svn 程序提供了两个子命令,用于显示存储在文件和目录上的属性的名称和值。 svn proplist 命令将列出路径上存在的属性的名称。一旦您知道节点上属性的名称,就可以使用 svn propget 单独请求它们的值。此命令将针对属性名称和路径(或一组路径)打印属性的值到标准输出流。

$ svn proplist calc/button.c
Properties on 'calc/button.c':
  copyright
  license
$ svn propget copyright calc/button.c
(c) 2006 Red-Bean Software

甚至还有 proplist 命令的变体,它将列出所有属性的名称和值。只需提供 --verbose (-v) 选项。

$ svn proplist -v calc/button.c
Properties on 'calc/button.c':
  copyright
    (c) 2006 Red-Bean Software
  license
    ================================================================
    Copyright (c) 2006 Red-Bean Software.  All rights reserved.

    Redistribution and use in source and binary forms, with or without
    modification, are permitted provided that the following conditions 
    are met:

    1. Redistributions of source code must retain the above copyright
    notice, this list of conditions, and the recipe for Fitz's famous
    red-beans-and-rice.
    …

最后一个与属性相关的子命令是 propdel。由于 Subversion 允许您存储具有空值的属性,因此您不能使用 svn propeditsvn propset 完全删除属性。例如,此命令不会产生预期效果

$ svn propset license "" calc/button.c
property 'license' set on 'calc/button.c'
$ svn proplist -v calc/button.c
Properties on 'calc/button.c':
  copyright
    (c) 2006 Red-Bean Software
  license
    
$

您需要使用 propdel 子命令完全删除属性。语法类似于其他属性命令

$ svn propdel license calc/button.c
property 'license' deleted from 'calc/button.c'.
$ svn proplist -v calc/button.c
Properties on 'calc/button.c':
  copyright
    (c) 2006 Red-Bean Software
$

还记得那些未版本化的修订属性吗?您也可以使用我们刚才描述的相同 svn 子命令来修改它们。只需添加 --revprop 命令行参数并指定您要修改其属性的修订版本。由于修订版本是全局的,因此只要您位于要修改其修订属性的存储库的工作副本中,您就不需要为这些与属性相关的命令指定目标路径。否则,您只需提供要修改的存储库中任何路径的 URL(包括存储库的根 URL)。例如,您可能希望替换现有修订版本的提交日志消息。[14] 如果您当前的工作目录是存储库工作副本的一部分,您可以简单地运行没有目标路径的 svn propset 命令

$ svn propset svn:log "* button.c: Fix a compiler warning." -r11 --revprop
property 'svn:log' set on repository revision '11'
$

但即使您没有从该存储库签出工作副本,您仍然可以通过提供存储库的根 URL 来影响属性更改

$ svn propset svn:log "* button.c: Fix a compiler warning." -r11 --revprop \
              http://svn.example.com/repos/project
property 'svn:log' set on repository revision '11'
$

请注意,修改这些未版本化属性的能力必须由存储库管理员显式添加(参见 名为“提交日志消息更正”的部分)。这是因为属性没有版本控制,因此,如果您在编辑时不小心,您就有丢失信息的风险。存储库管理员可以设置方法来防止这种丢失,默认情况下,禁用未版本化属性的修改。

[Tip] 提示

用户应尽可能使用 svn propedit 而不是 svn propset。虽然命令的最终结果相同,但前者将允许他们看到即将更改的属性的当前值,这有助于他们验证他们是否实际上正在进行他们认为正在进行的更改。这在修改未版本化的修订属性时尤其如此。此外,在文本编辑器中修改多行属性值比在命令行中更容易。

属性和 Subversion 工作流程

现在您已经熟悉了所有与属性相关的 svn 子命令,让我们看看属性修改如何影响通常的 Subversion 工作流程。正如我们之前提到的,文件和目录属性是版本化的,就像您的文件内容一样。因此,Subversion 为将其他人的修改干净地或与冲突合并到您自己的修改中提供了相同的机会。

与文件内容一样,您的属性更改是本地修改,只有当您使用 svn commit 将它们提交到存储库时才会永久保存。您的属性更改也很容易撤消——svn revert 命令会将您的文件和目录恢复到未编辑状态——内容、属性和所有内容。此外,您可以使用 svn statussvn diff 命令获取有关文件和目录属性状态的有趣信息。

$ svn status calc/button.c
 M      calc/button.c
$ svn diff calc/button.c
Property changes on: calc/button.c
___________________________________________________________________
Added: copyright
## -0,0 +1 ##
+(c) 2006 Red-Bean Software
$

请注意 status 子命令如何在第二列而不是第一列中显示 M。这是因为我们修改了 calc/button.c 上的属性,但没有修改其文本内容。如果我们同时更改了这两者,我们也会在第一列中看到 M。(我们在 名为“查看更改概述”的部分 中介绍 svn status)。

您可能还注意到 Subversion 目前显示属性差异的非标准方式。您仍然可以使用 svn diff 并将其输出重定向以创建可用的补丁文件。 patch 程序将忽略属性补丁——作为规则,它会忽略它不理解的任何噪声。不幸的是,这意味着要使用 patch 完全应用由 svn diff 生成的补丁,任何属性修改都需要手动应用。

Subversion 1.7 通过两种方式改善了这种情况。首先,它对属性差异的非标准显示至少是机器可读的——比 1.7 之前版本中显示的属性有所改进。但 Subversion 1.7 还引入了 svn patch 子命令,专门设计用于处理 svn diff 输出可能携带的附加信息,并将这些更改应用于 Subversion 工作副本。与我们的主题特别相关的是,由 svn diff 在 Subversion 1.7 或更高版本中生成的补丁文件中出现的属性差异可以由 svn patch 命令自动应用于工作副本。有关 svn patch 的更多信息,请参见 svn patchsvn 参考——Subversion 命令行客户端 中。

[Note] 注意

svn diff 报告属性更改的方式有一个例外:对 Subversion 的特殊 svn:mergeinfo 属性的更改——用于跟踪已在您的存储库中执行的合并的信息——以更易于人类阅读的方式进行描述。这对必须阅读这些描述的人类来说非常有用。但这也导致修补程序(包括 svn patch)将这些更改描述跳过作为噪声。这听起来可能像个错误,但实际上并非如此,因为此属性旨在仅由 svn merge 子命令管理。有关合并跟踪的更多信息,请参见 第 4 章,分支和合并

继承属性

Subversion 1.8 引入了继承属性的概念。实际上,使属性可继承没有任何特别之处。事实上,所有版本化的属性都是可继承的!1.8 之前和之后的版本化属性之间的主要区别在于,后者提供了一种机制来查找目标路径的父级上设置的属性,即使这些父级在工作副本中找不到。

通用属性继承体现在几个命令中。首先,svn proplist svn propget 子命令可以通过使用 --show-inherited-props 选项来检索 URL 或工作副本路径的父级上的所有属性。您可以将此视为 --recursive 子命令操作的反面——不是递归地“向下”进入目标的子目录,而是具有 --show-inherited-props 选项的子命令向上查看“向上”进入目标的父目录。 svnlook propgetsvnlook proplist 子命令也以类似的方式使用 --show-inherited-props 选项。

让我们看一个关于它是如何工作的例子。在工作副本根目录上执行以下递归 propget 发现 svn:auto-props 属性在子命令的目标和它的一个子目录 site 上都已设置

$ svn pg svn:auto-props --verbose -R .
Properties on '.':
  svn:auto-props
    *.py = svn:eol-style=native
    *.c = svn:eol-style=native
    *.h = svn:eol-style=native

Properties on 'site':
  svn:auto-props
    *.html = svn:eol-style=native

如果我们改为将子命令的目标设置为子目录 site,那么使用 --show-inherited-props 选项,我们会发现 svn:auto-props 属性在目标其父级上设置。父级的属性被标示为“继承的”

$ svn pg svn:auto-props --verbose --show-inherited-props site
Inherited properties on 'site',
from '.':
  svn:auto-props
    *.py = svn:eol-style=native
    *.c = svn:eol-style=native
    *.h = svn:eol-style=native

Properties on 'site':
  svn:auto-props
    *.html = svn:eol-style=native

在之前的示例中,工作副本的根目录对应于存储库的根目录,但当情况并非如此时,也可以从工作副本之外继承属性。让我们签出之前的示例中的 site 目录,使其成为工作副本的根目录

$ svn co http://svn.example.com/repos site-wc
A    site-wc/publish
A    site-wc/publish/ch2.html
A    site-wc/publish/news.html
A    site-wc/publish/ch3.html
A    site-wc/publish/faq.html
A    site-wc/publish/index.html
A    site-wc/publish/ch1.html
 U   site-wc
Checked out revision 19.

$ cd site-wc

现在,当我们在工作副本路径上检查继承属性时,我们可以看到一个属性是从工作副本父级继承的,另一个属性是从存储库父级继承的,它代表了工作副本根目录“之上”的位置

$ svn pg svn:auto-props --verbose --show-inherited-props publish
Inherited properties on 'publish',
from 'http://svn.example.com/repos':
  svn:auto-props
    *.py = svn:eol-style=native
    *.c = svn:eol-style=native
    *.h = svn:eol-style=native

Inherited properties on 'publish',
from '.':
  svn:auto-props
    *.html = svn:eol-style=native
[Warning] 警告

您只能从您有读取权限的存储库路径继承属性 - 请参阅名为“内置身份验证和授权”的部分名为“授权选项”的部分。如果您没有对父路径的读取权限,那么它将显示为父路径没有设置任何属性。

如上所述,svnlook proplistsvnlook propget 命令也支持 --show-inherited-props 选项,但它们不是按工作副本路径或 URL 报告继承的属性,而是按存储库路径列出。

$ svnlook pg repos svn:auto-props /site/publish --show-inherited-props -v
Inherited properties on '/site/publish',
from '/':
  svn:auto-props
    *.py = svn:eol-style=native
    *.c = svn:eol-style=native
    *.h = svn:eol-style=native

Inherited properties on '/site/publish',
from '/site':
  svn:auto-props
    *.html = svn:eol-style=native

从工作副本根目录以上继承的属性在最初检出工作副本时会缓存在工作副本的管理数据库中,然后在每次更新工作副本时都会刷新。这意味着您不需要访问存储库即可查看继承的属性。这使 Subversion 子命令能够传统上不需要访问存储库(例如 svn add)仍然保持“断开连接”,同时仍然访问从工作副本中未找到的路径继承的属性。但是,这也意味着从工作副本根目录以上继承的属性可能自您上次更新后已更改,导致您的本地缓存过时。因此,如果您需要某些继承属性的绝对最新值,最安全的做法始终是先更新您的工作副本,或者直接查询存储库。

此时,您可能会想,“好技巧,但有什么用呢?”就其本身而言,属性继承并不是很有用。在 1.8 之前,Subversion 的所有保留 svn:* 属性(以及您自己的所有自定义用户属性)只适用于设置它们的路径,或者最多适用于路径的直接子级[15] 相反,可继承属性是 Subversion 用来执行其他更有趣的事情的工具,例如使用 svn:auto-props 属性设置自动属性或使用 svn:global-ignores 属性设置存储库范围的忽略 - 请参阅名为“自动属性设置”的部分名为“忽略未版本化的项目”的部分以获取有关这些特殊属性及其使用方法的更多信息。

[Tip] 提示

目前,可继承属性主要仅在 svn:auto-props svn:global-ignores 属性方面有用,但这并不意味着这两个属性是故事的结尾。期待在 Subversion 的未来版本中使用可继承属性构建更多功能 - 日志消息模板机制就是一个例子。同时,请随时按照您希望的方式使用此功能。您希望应用于整个存储库(或其中一部分较大的子树)的任何版本化元数据都可以轻松地存储在存储库根目录(或相应的子树)的属性中。我们怀疑一些用户和管理员会想出一些我们从未考虑过的巧妙方法来使用可继承属性。

自动属性设置

属性是 Subversion 的一个强大功能,它充当了许多在本章和其它章节中讨论的 Subversion 功能的关键组成部分 - 文本差异和合并支持、关键字替换、换行符转换等等。但是,要充分利用属性,必须将它们设置在正确的文件和目录上。不幸的是,这一步很容易在日常工作中被遗忘,尤其是在未设置属性通常不会导致明显的错误(至少与未能将文件添加到版本控制相比)的情况下。为了帮助您的属性应用于需要它们的地方,Subversion 提供了一些简单但有用的功能。

无论何时使用 svn addsvn import 命令将文件引入版本控制时,Subversion 都会尝试通过自动设置一些常见的文件属性来提供帮助。首先,在文件系统支持执行权限位的操作系统上,Subversion 会自动在启用了执行位的已添加或导入的新文件上设置 svn:executable 属性。(有关此属性的更多信息,请参阅本章后面名为“文件可执行性”的部分。)

其次,Subversion 会尝试确定文件的 MIME 类型。如果您已配置 mime-types-files 运行时配置参数,Subversion 会尝试在该文件中查找文件的扩展名的 MIME 类型映射。如果找到这样的映射,它会将文件的 svn:mime-type 属性设置为它找到的 MIME 类型。如果未配置任何映射文件,或未找到文件的扩展名的映射,Subversion 会回退到启发式算法以确定文件的 MIME 类型。根据其构建方式,Subversion 1.7 可以使用文件扫描库[16] 根据文件内容检测文件的类型。如果所有方法都失败,Subversion 将使用它自己的非常基本的启发式方法来确定文件是否包含非文本内容。如果是这样,它会自动将该文件的 svn:mime-type 属性设置为 application/octet-stream(通用 这是一组字节 MIME 类型)。当然,如果 Subversion 猜错了,或者您希望将 svn:mime-type 属性设置为更精确的值 - 可能是 image/pngapplication/x-shockwave-flash - 您始终可以删除或编辑该属性。(有关 Subversion 使用 MIME 类型的更多信息,请参阅本章后面名为“文件内容类型”的部分。)

[Note] 注意

UTF-16 通常用于编码语义内容本质上是文本的文件,但编码本身大量使用超出典型 ASCII 字符字节范围的字节。因此,Subversion 往往会将此类文件归类为二进制文件,这令希望对这些文件进行基于行的差异和合并、关键字替换以及其他操作的用户感到沮丧。

Subversion 还通过其运行时配置系统(请参阅名为“运行时配置区域”的部分)提供了一个更灵活的自动属性设置功能,允许您创建文件名模式到属性名称和值的映射。同样,这些映射会影响添加和导入,不仅可以覆盖 Subversion 在这些操作期间做出的默认 MIME 类型决策,而且还可以设置其他 Subversion 或自定义属性。例如,您可能会创建一个映射,表示无论何时添加 JPEG 文件 - 那些名称与模式 *.jpg 匹配的文件 - Subversion 应该自动将这些文件的 svn:mime-type 属性设置为 image/jpeg。或者,任何与 *.cpp 匹配的文件都应该将 svn:eol-style 设置为 native,并将 svn:keywords 设置为 Id。有关运行时配置中自动属性支持的更多详细信息,请参阅名为“常规配置”的部分

虽然通过运行时配置系统提供的自动属性支持肯定很方便,但 Subversion 管理员可能更喜欢一组属性定义,所有连接的客户端在操作从给定服务器检出的工作副本时都会自动考虑这些定义。Subversion 1.8 及更高版本客户端通过 svn:auto-props 可继承属性支持此类功能。

当文件被添加或导入时,svn:auto-props 属性的工作方式类似于运行时配置,以自动设置文件的属性。svn:auto-props 属性的值应与 auto-props 运行时配置选项相同(即格式为 FILE_PATTERN = PROPNAME=VALUE[;PROPNAME=VALUE ...] 的任意数量的键值对)与 auto-props 运行时选项一样,可以使用 --no-auto-props 选项忽略 svn:auto-props 属性,但与配置选项不同,当 enable-auto-props 配置选项设置为 no 时,svn:auto-props 属性不会被禁用。

例如,假设您已经检出了 trunk 分支的工作副本,并且需要添加一个新文件(假设您的运行时配置中的自动属性已禁用)

$ svn st
?       calc/data.c

$ svn add calc/data.c
A         calc/data.c

$ svn proplist -v calc/data.c
Properties on 'calc/data.c':
  svn:eol-style
    native

请注意,将未版本化的文件 data.c 置于版本控制之下后,svn:eol-style 属性会自动设置在其上。由于我们假设 auto-props 运行时配置选项已禁用,因此我们知道 svn:auto-props 属性必须设置在 data.c 的某个父路径上。使用带 --show-inherited-props 选项的 svn propget 子命令,我们可以看到事实确实如此

$ svn propget svn:auto-props --show-inherited-props -v calc
Inherited properties on 'calc',
from 'http://svn.example.com/repos':
  svn:auto-props
    *.py = svn:eol-style=native
    *.c = svn:eol-style=native
    *.h = svn:eol-style=native

svn:global-ignores 属性及其类似的运行时配置 global-ignores(它们是组合的)不同,svn:auto-props 属性会覆盖 auto-props 运行时配置,如果它为与运行时配置相同的模式定义了自动属性。从一个路径继承的自动属性[17] 也可以覆盖从另一个路径继承的相同模式。这些覆盖的层次结构按以下方式工作

  • 针对给定模式在 svn:auto-props 中定义的自动属性将覆盖 auto-props 运行时配置中针对相同模式的相同自动属性。

  • 如果针对给定模式的自动属性从多个父级的 svn:auto-props 属性继承而来,则路径上较近的父级将覆盖较远的父级。

  • 针对给定模式在路径上明确设置的 svn:auto-props 属性中定义的自动属性将覆盖从任何父级继承的针对相同模式的相同自动属性。

让我们看一个例子。假设您有以下运行时配置

[miscellany]
enable-auto-props = yes
[auto-props]
*.py  = svn:eol-style=CR
*.c   = svn:eol-style=CR
*.h   = svn:eol-style=CR
*.cpp = svn:eol-style=CR

您想要在工作副本的 calc 目录中添加三个文件

$ svn st
?       calc/data-binding.cpp
?       calc/data.c
?       calc/editor.py

让我们检查一下哪些 svn:auto-props 应用于 calc

$ svn propget svn:auto-props -v --show-inherited-props calc
Inherited properties on 'calc',
from 'http://svn.example.com/repos':
  svn:auto-props
    *.py = svn:eol-style=native
    *.c = svn:eol-style=native
    *.h = svn:eol-style=native

Inherited properties on 'calc',
from '.':
  svn:auto-props
    *.py = svn:eol-style=native
    *.c = svn:keywords=Author Date Id Rev URL

当我们添加这三个文件时,我们期望有哪些自动属性?我们将这三个文件添加到版本控制,然后检查

$ svn add calc --force
A         calc/data-binding.cpp
A         calc/data.c
A         calc/editor.py

文件 data-binding.cpp 只有一个匹配的模式,即运行时配置中的 *.cpp = svn:eol-style=CR,因此显然 svn:eol-style 属性被设置为 CR

$ svn proplist -v calc/data-binding.cpp
Properties on 'calc/data-binding.cpp':
  svn:eol-style
    CR

文件 editor.py 在运行时配置和两个 svn:auto-props 属性中匹配一个模式,但根据上面描述的层次结构,在 calc 上明确设置的属性,即 *.py = svn:eol-style=native,优先级更高。因此,svn:eol-style 属性被设置为 native:

$ svn proplist -v calc/editor.py
Properties on 'calc/editor.py':
  svn:eol-style
    native

文件 data.c 也匹配运行时配置和继承的两个 svn:auto-props 属性中的模式。 svn:keywords 自动属性仅在 calc 上定义一次,因此 data.c 会自动获取该属性。 但是, calc 上的 svn:auto-props 未定义 svn:eol-style 值,因此最近的继承父级 http://svn.example.com/repos 提供了该值。

$ svn proplist -v calc/data.c
Properties on 'calc/data.c':
  svn:eol-style
    native
  svn:keywords
    Author Date Id Rev URL
[Warning] 警告

覆盖自动属性仅适用于 完全相同 的模式。 如果要添加或导入的文件匹配多个模式,则无法保证将应用哪个模式的自动属性。 例如,假设您想要在目录 bar 中添加文件 foo.cpp 。 此外,假设 svn:auto-props 属性在 bar 上设置,其值为

*.c*  = svn:eol-style=native
*.cpp = svn:eol-style=native;svn:keywords=Author Date Id Rev URL

由于 foo.cpp 匹配这两个模式,因此无法知道在添加时是否会在 foo.cpp 上设置 svn:keywords 属性。

关于 svn:auto-props 的最后一点说明。 此属性(以及类似的 svn:global-ignores ,请参阅 名为“忽略未版本控制的项目”的部分)仅向理解属性含义的客户端提供 建议。 较旧的客户端会忽略这些属性, --no-auto-props 选项将忽略它们,用户可能会在设置自动属性后手动更改或删除它们——有许多方法可以绕过 svn:auto-props 中包含的建议属性。 鉴于此,管理员仍然需要使用钩子脚本验证添加到文件和目录中的属性以及修改的文件和目录是否符合管理员的首选策略,拒绝不符合此方式的提交。 (有关钩子脚本的更多信息,请参阅 名为“实现仓库钩子”的部分。)

Subversion 保留属性

在本节中,我们将简要总结 Subversion 为自身保留的所有属性。 我们将查看两种类型的属性——与单个版本控制文件和目录关联的属性,以及与修订版本关联的属性。

版本控制属性

这些是 Subversion 为自身保留的版本控制(或节点)属性

svn:auto-props

如果存在于目录上,该值是一组自动属性定义,这些定义适用于目录下的所有文件。 请参阅 名为“自动属性设置”的部分

svn:executable

如果存在于文件上,客户端将在 Unix 主机工作副本中使文件可执行。 请参阅 名为“文件可执行性”的部分

svn:mime-type

如果存在于文件上,该值指示文件的 MIME 类型。 这使客户端能够确定在更新期间是否可以安全地执行基于行的上下文合并,并且还可以影响通过 Web 浏览器获取文件时的行为方式。 请参阅 名为“文件内容类型”的部分

svn:ignore

如果存在于目录上,该值是 未版本控制的 文件模式列表,这些模式将被 svn status 和其他子命令忽略。 请参阅 名为“忽略未版本控制的项目”的部分

svn:global-ignores

如果存在于目录上,该值是 未版本控制的 文件模式列表,这些模式将被 svn status 和其他子命令忽略。 与 svn:ignore 不同,这些模式适用于目录下 所有 未版本控制的子树,而不仅仅是目录的直接文件子级。 请参阅 名为“忽略未版本控制的项目”的部分

svn:keywords

如果存在于文件上,该值告诉客户端如何在文件中扩展特定关键字。 请参阅 名为“关键字替换”的部分

svn:eol-style

如果存在于文件上,该值告诉客户端如何在工作副本和导出树中操作文件的行尾符。 请参阅 名为“行尾字符序列”的部分svn export

svn:externals

如果存在于目录上,该值是客户端应检出的其他路径和 URL 的多行列表。 请参阅 名为“外部定义”的部分

svn:special

如果存在于文件上,则表示该文件不是普通文件,而是符号链接或其他特殊对象。 [18]

svn:needs-lock

如果存在于文件上,则告诉客户端在工作副本中使文件只读,作为编辑开始之前应锁定文件的提醒。 请参阅 名为“锁定通信”的部分

svn:mergeinfo

由 Subversion 用于跟踪合并数据。 有关详细信息,请参阅 名为“Mergeinfo 和预览”的部分,但除非您 确实 知道自己在做什么,否则不要编辑此属性。

未版本控制的属性

以下是 Subversion 为自身保留的未版本控制(或修订版本)属性。 其中大多数出现在仓库中的每个修订版本上,包含有关该修订版本中所做更改的来源和性质的重要信息。

svn:author

如果存在,则包含创建修订版本的人员的经过身份验证的用户名。 (如果不存在,则匿名提交了该修订版本。)

svn:autoversioned

如果存在,则该修订版本是通过自动版本控制功能创建的。 请参阅 名为“自动版本控制”的部分

svn:date

包含创建修订版本的 UTC 时间,以 ISO 8601 格式表示。 该值来自 服务器 机器的时钟,而不是客户端的时钟。

svn:log

包含描述修订版本的日志消息。

Subversion 工具链中的某些辅助工具——即 svnrdumpsvnsync——也使用未版本控制的属性来进行自身记账。 这些属性仅在这些工具正在操作的仓库的修订版本 0 上找到。 有关 svnrdumpsvnsync 以及它们提供的功能的更多信息,请参阅 第 5 章,仓库管理。 以下是由这些工具创建和管理的属性。

svn:rdump-lock

用于通过 svnrdump load 临时强制对仓库进行互斥访问。 此属性通常仅在执行此类操作时观察到——或者当 svnrdump 命令未能干净地断开与仓库的连接时。 (此属性仅在它出现在修订版本 0 上时才相关。)

svn:sync-currently-copying

包含来自源仓库的修订版本号,该修订版本号当前正在通过 svnsync 工具镜像到此仓库。 (此属性仅在它出现在修订版本 0 上时才相关。)

svn:sync-from-uuid

包含该仓库已通过 svnsync 工具初始化为镜像的仓库的 UUID。 (此属性仅在它出现在修订版本 0 上时才相关。)

svn:sync-from-url

包含该仓库已通过 svnsync 工具初始化为镜像的仓库目录的 URL。 (此属性仅在它出现在修订版本 0 上时才相关。)

svn:sync-last-merged-rev

包含最近成功镜像到此仓库的源仓库的修订版本。 (此属性仅在它出现在修订版本 0 上时才相关。)

svn:sync-lock

用于通过 svnsync 镜像操作临时强制对仓库进行互斥访问。 此属性通常仅在执行此类操作时观察到——或者当 svnsync 命令未能干净地断开与仓库的连接时。 (此属性仅在它出现在修订版本 0 上时才相关。)



[13] 如果您熟悉 XML,这几乎是 XML Name 语法的 ASCII 子集。

[14] 修复提交日志消息中的拼写错误、语法错误和 just-plain-wrongness 可能是 --revprop 选项最常见的用例。

[15] 对此的唯一显著例外是 svn:mergeinfo 属性,它是可继承的——请参阅 名为“Mergeinfo 和预览”的部分

[16] 目前,libmagic 是用于完成此操作的支持库。

[17] 请记住,用户只能从他们具有读取权限的路径继承属性。 因此,如果管理员在某个高级父路径(例如仓库根目录)上设置 svn:auto-props ,他们需要确保所有用户都具有对该路径的读取权限,否则所需的自动属性设置将不会生效。

[18] 截至撰写本文时,符号链接确实是唯一的 特殊 对象。 但在 Subversion 的未来版本中可能会有更多。

TortoiseSVN 官方中文版 1.14.7 发布