SVN提交后钩子以修改外部 [英] SVN post-commit hook to modify externals

查看:211
本文介绍了SVN提交后钩子以修改外部的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个Subversion设置,它相当广泛地使用svn:externals(在一个项目中有5个以上的外部引用,并且大多数都在同一个存储库中,一个或两个在不同的存储库中,但仍在同一服务器上).当前,svn:externals属性的设置方式是使它们具有所引用项目的完整URL(即"https://[服务器]:[port]/svn/Repository1/Projects/...)

最近,我已经使用svnsync设置了SVN镜像,该镜像将我们的存储库备份到外部异地设施.我们需要能够从远程站点的那些镜像存储库中进行只读签出,这似乎在大多数情况下都可以正常工作,除了当它尝试拉外部设备时,它仍然引用我们本地的本地服务器.

不确定这是否是最好的方法,但是我想在远程位置设置某种提交后的钩子,这将修改svn:externals的属性并替换本地主机名.此处带有远程服务器主机名的服务器.该挂钩将在svnsync进行的每次提交之后运行.

理想情况下,我们希望避免在主存储库中修改我们的svn:externals属性,使其不包括服务器名称.

以前有人遇到过这个问题吗?最好的方法是什么?

解决方案

您必须了解svn:externals是文件上的属性,修改它们需要提交.如果您有 mirror ,并且修改了svn:external,则说明您正在创建新的远程版本并破坏了镜像.修订将不再排队.

尽管在当时看来是个好主意,但svn:externals在项目中可能非常糟糕.想象一个这样的项目:

http://vegibank.com/svn/trunk/project1

我在此目录中有一个svn:external

$ svn pset svn:external "^/trunk/project2/foo foo" .

之所以这样做,是因为foo目录是多个项目的共享文件集.

现在,我为project1创建一个标签:

$ svn cp http://vegibank.com/svn/trunk/project1 http://vegibank.com/svn/tags/1.2.3

看起来不错-除了未标记project1/foo目录之外. 它链接到project2/foo 的中继.

我对标签的假设是标签永远不会改变,但这不是事实.中继上project2/foo的工作仍在进行中,这改变了我的标签所代表的含义.如果我在1.2.3版中有一个错误,并且我决定签出我的标签以查看可能是什么问题,那么我不一定会得到project1/foo中发布的内容-我正在从主干获得最新的信息.

处理此问题的更好方法是创建一个发行版存储库,将各种项目之间通用的代码构建为某种预编译的工件,并使您的项目依赖于该工件的那个版本.它最终与依赖于libz.so特定版本的C程序或依赖于org.apache.commons.httpd 1.6版的Java项目没有什么不同.

这将消除对svn:externals的使用,并简化镜像.您可以镜像发布存储库以及源存储库.

如果您坚持使用svn:external,请不要使用完整的URL.而是使用相对URL.

例如,如果您在上面设置了`svn:external而不是这个:

$ svn pset svn:external "^/trunk/project2/foo foo" .

为此:

$ svn pset svn:external "../project2/foo foo" .   #property on ^/trunk/project1

现在,如果我创建这样的标签:

$ svn cp http://vegibank.com/svn/trunk http://vegibank.com/svn/tags/1.2.3

我同时标记了project1project2.现在,我的svn:external指的是http://vegibank.com/svn/tags/1.2.3/project2/foo.

您需要的是一种以这种方式强制执行svn:externals的方法,并且您可以使用pre-commit钩子拒绝具有引用trunkbranches目录且没有svn:external设置的任何提交.要么指定实际版本.

We have a Subversion setup that makes fairly extensive use of svn:externals (more than 5 external references in one project, and while most are in the same repository, one or two are in a different repository but still on the same server). Currently, the svn:externals properties are set up in a way where they have the full URL of the referenced project (i.e. "https://[server]:[port]/svn/Repository1/Projects/...)

Recently, I have set up an SVN mirror using svnsync which backs up our repositories to an external off-site facility. We need the ability to do read-only checkouts from those mirrored repositories at the remote site, which seems to work fine for the most part except when it tries to pull the externals, it still references our local on-site server.

Not sure if this is the best way to go about it, but I would like to set up some sort of post-commit hook at the remote location which would modify the properties of svn:externals and replace the hostname of our local server here with the hostname of the remote server there. This hook would run after each commit made by svnsync.

Ideally, we would like to avoid modifying our svn:externals properties at the main repository to not include the server name.

Has anyone ran into this issue before? What is the best way to go about it?

解决方案

You must understand that svn:externals are a property on a file, and modifying them requires a commit. If you have a mirror, and you modify the svn:external, you're creating a new remote version and breaking your mirror. The revisions will no longer line up.

Although it seemed like a neat idea at the time, svn:externals can be very bad in a project. Imagine a project like this:

http://vegibank.com/svn/trunk/project1

And I have on this directory an svn:external

$ svn pset svn:external "^/trunk/project2/foo foo" .

I do this because the foo directory is a shared set of files for multiple projects.

Now, I create a tag for project1:

$ svn cp http://vegibank.com/svn/trunk/project1 http://vegibank.com/svn/tags/1.2.3

Looks nice -- except the project1/foo directory isn't tagged. It's linked to the trunk of project2/foo.

My assumption with a tag is that the tag never changes, but this isn't true. Work is still being done on project2/foo on trunk, and that changes what my tag represents. If I have a bug in release 1.2.3, and I decide to checkout my tag to see what could be the problem, I'm not getting necessarily what I released in project1/foo -- I'm getting the latest from trunk.

A better way to handle this is to create a release repository, build the code that's common between various projects as some sort of pre-compiled artifact and have your project depend upon that version of that artifact. It ends up being no different than a C program dependent upon a particular version of libz.so or a Java project dependent upon version 1.6 of org.apache.commons.httpd.

This will eliminate the use of svn:externals and simplify your mirroring. You could mirror the release repository as well as the source repository.

If you insist upon using svn:external, don't use the full URL. Instead, use relative URLs.

For example, if you had setup your `svn:external above instead of this:

$ svn pset svn:external "^/trunk/project2/foo foo" .

to do this:

$ svn pset svn:external "../project2/foo foo" .   #property on ^/trunk/project1

Now, if I create a tag like this:

$ svn cp http://vegibank.com/svn/trunk http://vegibank.com/svn/tags/1.2.3

I'm tagging both project1 and project2. Now, my svn:external refers to http://vegibank.com/svn/tags/1.2.3/project2/foo.

What you need is a way to enforce svn:externals in this way, and you can use a pre-commit hook to reject any commit that has a svn:external set that references the trunk or branches directory without either specifying an actual revision.

这篇关于SVN提交后钩子以修改外部的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆