我正在使用 SharpSvn NuGet 包(版本 1.14003.272)通过 https 访问 SVN 服务器。
注意:我的电脑设置为自动调整夏令时(夏令时)时间,我假设服务器(运行 Windows Server)也这样做。因此,当我说某件事使用时区 CET (UTC+1) 或 ET (UTC-5) 时,此时实际上可能是 CEST (UTC+2) 或 EDT (UTC-4)。
我的计算机(位于德国)的默认时区为 CET。这大概与同样位于德国的服务器相同。
使用默认设置,一切正常。
但是,当我在启动程序之前手动将电脑的时区调整为东部时间 (UTC-5) 时,
SvnClient.GetLog
功能会失败,并显示 SvnRepositoryIOException
。
此错误仅在程序启动时时区为 UTC-X 时出现,而不是在我选择 UTC 或 UTC+X 时区时出现。
以下是所有相关的异常属性:
HResult: -2146233088
InnerException: null
Message: "Unexpected HTTP status 400 'Bad Request' on '/path/to/repository/!svn/me'"
Source: "SharpSvn"
StackTrace: <see below>
SvnErrorCategory: 35
SvnErrorCode: SVN_ERR_RA_DAV_REQUEST_FAILED (175002)
这是堆栈跟踪:
at SharpSvn.SvnClientArgs.HandleResult(SvnClientContext client, SvnException error, Object targets)
at SharpSvn.SvnClient.InternalLog(ICollection`1 targets, Uri logRoot, SvnRevision altPegRev, SvnLogArgs args, EventHandler`1 logHandler)
at SharpSvn.SvnClient.Log(ICollection`1 targets, SvnLogArgs args, EventHandler`1 logHandler)
at SharpSvn.SvnClient.GetLog(ICollection`1 targets, SvnLogArgs args, Collection`1& logItems)
at [stack of my methods starts here]
我的
App.xaml.cs
看起来像这样:
public partial class App : PrismApplication
{
protected override void Initialize()
{ // X
base.Initialize();
// [...]
}
// [...]
}
我在标有
// X
的行上设置了断点;据我所知,这是程序运行的第一行代码。但不归路的关键更早,就在框架的启动代码中的某个地方:
X
行中命中断点,将时区更改为 UTC-X,继续执行 - GetLog
有效。X
,更改为 UTC 或任何 UTC+X,继续 - GetLog
失败。以下是我在尝试查找失败点时所做的一些观察:
此时,我什至不知道该看哪里,因为我对 WebDAV 不太了解,也无法解释为什么时区设置只在应用程序启动期间重要,以及为什么它只对
GetLog
重要,但是不是其他命令。
我找到了避免此错误的解决方案。
在我自己的
SvnGetLog
方法中,代码正在创建一个“所有修订版”SvnRevisionRange
,本质上是这样的:
var range = new SvnRevisionRange(DateTime.MinValue, DateTime.MaxValue);
但是,
DateTime.MinValue
和DateTime.MaxValue
属于DateTimeKind.Unspecified
而不是DateTimeKind.Utc
。
有多种方法可以创建有效的
SvnRevisionRange
:
DateTime.MinValue
替换为 new DateTime(DateTime.MinValue.Ticks, DateTimeKind.Utc)
,并对 DateTime.MaxValue
执行相同操作。1970-01-01 00:00:00 Unspecified
作为 from
而不是框架的 DateTime.MinValue
即 0001-01-01 00:00:00 Unspecified
。new SvnRevisionRange(SvnRevision.Zero, SvnRevision.Head)
(对我来说不是一个选项,因为所需的 API 有 DateTime
参数)我无法真正提供明确的解释内部发生了什么,但我可以想象这样的事情:
在应用程序启动期间,.NET 框架存储运行时环境的时区,并随后使用它将
Unspecified
时间戳转换为本地时间或 UTC(基本上是“有根据的猜测”)。
当我从在 UTC 或 UTC+X 环境中启动的程序发送从
MinValue
开始的请求时,将该时间戳转换为 UTC 会将其保留在该日期,甚至将其向后移动到 0 年。也许这会触发捕获这些值并假设“开始”而不使用实际日期值的特殊情况。
但是,当我在 UTC-X 启动时,
MinValue
会转换为 hour X of day 0001-01-01
,它不是 0 或负数,因此特殊情况不会触发。这可能会导致 SVN 实际上尝试根据该日期值进行一些实际计算,这会导致错误,因为它超出了 UNIX 时间,或者导致下溢,导致 from > to
或类似的情况。
正如我所说,我完全不确定它是如何工作的以及会发生什么,但它适合所有症状。最重要的是,使用
DateTimeKind.Utc
而不是 DateTimeKind.Unspecified
解决了我的问题。