【问题标题】:How to download only updated files from TFS in local directory using Powershell如何使用 Powershell 仅从本地目录中的 TFS 下载更新的文件
【发布时间】:2018-11-28 18:33:00
【问题描述】:

我需要将选定的文件夹从 TFS 源代码控制下载到本地文件夹。我可以使用以下脚本执行此操作:

Add-PSSnapin Microsoft.TeamFoundation.PowerShell
$securePass = ConvertTo-SecureString -AsPlainText -Force -String "mypassword"
$uri = "serverURL"
$cred =  New-Object System.Management.Automation.PSCredential("myusername",$securePass)

$tfsServer = Get-TfsServer -Name $uri -Credential $cred
$structureService = $tfsServer.GetService("Microsoft.TeamFoundation.Server.ICommonStructureService")

$versionControlService = $tfsServer.GetService("Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer")

$pathsToDownload=[System.Collections.ArrayList]@()
$pathsToDownload.add("$/myfirstPath")
$pathsToDownload.add("$/mysecondPath")
$pathsToDownload.add("$/mythirdPath")

$localTFSRoot = "c:\tfs"
$serverRoot = "$/"
foreach ($serverPath in $pathsToDownload) {
  write-host "Working with $serverPath"
  $items = Get-TfsChildItem -Server $tfsServer -Item $serverPath -Recurse
  foreach ($item in $items) {
    $destinationPath=$($Item.ServerItem.Replace($serverRoot,$localTFSRoot)).replace("\","/")
    write-host "Downloading $destinationPath"
    if ($item.ItemType -eq "Folder") {
       #create directory if it doesn't already exist
       if (-Not (Test-Path $destinationPath -PathType Container -IsValid)) {
          New-Item -ItemType Directory -Path $destinationPath -Force
       }
    } else {
       $versionControlService.DownloadFile($item.ServerItem,$destinationPath)
    }
  }
}

但是,此脚本每次都会下载所有文件。仅当文件发生更改时,我才想下载文件。有没有办法通过powershell操作来执行这样的操作?我不确定 getItem 与 downloadfile 的作用。

感谢您的帮助。

更新*** 我可以使用工作区路由进行下载,但如果它仅适用于更新,我还没有尝试过。 但是,workspace.get() 正在下载而没有任何详细输出。有没有办法让它列出它正在使用的文件,这样用户就不会认为它在下载时被挂起?

if ( (Get-PSSnapin -Name Microsoft.TeamFoundation.PowerShell -ErrorAction SilentlyContinue) -eq $null ) {
 Add-PSSnapin Microsoft.TeamFoundation.PowerShell
}
$securePass = ConvertTo-SecureString -AsPlainText -Force -String "mypassword"
$uri = "https://myserver"
$cred =  New-Object System.Management.Automation.PSCredential("myusername",$securePass)

$tfsServer = Get-TfsServer -Name $uri -Credential $cred
$structureService = $tfsServer.GetService("Microsoft.TeamFoundation.Server.ICommonStructureService")
$versionControlService = $tfsServer.GetService("Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer")

$workSpaceName = $env:USERNAME + "-IMAG"

$localTFSWorkspace="c:\tfswspace"
$serverRoot = "$/myproject"
$pathsToDownload=[System.Collections.ArrayList]@()
$pathsToDownload.add("$/myproject/path1")
$pathsToDownload.add("$/myproject/path2")

$testPath = $($pathsToDownload[0].Replace($serverRoot,$localTFSWorkspace)).replace("/","\")

if (!(Test-Path $localTFSWorkspace -PathType Container)) {
  New-Item $localTFSWorkspace -ItemType Directory -Force
}

# Check if workspace already exists
     $workspace = $versionControlService.TryGetWorkspace($testPath)
     if ($workspace -eq $null) {
       #Workspace doesn't exist, we need to create one
       $workspace = $versionControlService.CreateWorkspace($workSpaceName,$cred.UserName, 'Workspace for Repository Sync')
     }

 #create mappings if these don't exist 
 foreach ($serverPath in $pathsToDownload) {
      $localPath = $($serverPath.Replace($serverRoot,$localTFSWorkspace)).replace("/","\")
      if (!(Test-Path $localPath -PathType Container)) {
         New-Item $localPath -ItemType Directory -Force
      }

    $workingFolder =  $workspace.TryGetWorkingFolderForServerItem($serverPath)

    if ($workingFolder -eq $null) {
      #create mapping here
      $workspace.Map($serverPath,$localPath)
    }
 }
 # Now mappings are done -- get items now
 $workspace.get()

【问题讨论】:

  • 您使用的是什么版本的 tfs?我觉得你应该在某处包含一个设置为最新的 VersionSpec。
  • 是TFS 2013。我的理解是downloadFile总是会得到最新版本。但是,它并不“知道”已经存在本地副本。
  • 我已经有一段时间没有使用 TFS API 的东西了,但是你有没有试过下载一个文件,等几分钟,再做一次,然后比较第一个到第二个的时间戳下载?通常,如果 TFS 认为文件已被下载,它会避免将文件下载到工作区。
  • 是的,但在我的脚本中,我没有创建或定义工作区。它只是一个本地目录。
  • 这可能是您的问题的根源。它不跟踪文件。

标签: powershell tfs


【解决方案1】:

您需要创建一个工作区来获取所有文件。当您执行Get 时,您将看到所有文件都已下载到工作区中。如果工作区中的文件是最新的,则不会下载任何文件。一旦 TFS 中有新的更新文件,执行Get 后,只会替换更新的文件。下面是一段关于如何创建工作区的 C# 代码 sn-p:

            TfsTeamProjectCollection tfs = new TfsTeamProjectCollection(new Uri("http://tfs:8080/tfs/defaultCollection"));
            var versioncontrols = tfs.GetService<VersionControlServer>();

            var workspace = versioncontrols.CreateWorkspace("workspacename", "workspaceowner");

            String ServerFolder = @"$/xxxx/xxxx";
            String LocalFolder = @"E:\test";

            WorkingFolder workfolder = new WorkingFolder(ServerFolder, LocalFolder);
            workspace.CreateMapping(workfolder);

            workspace.Get();

【讨论】:

  • 谢谢。是的,我能够使用 PS 执行此操作(请查看更新的问题)。但是,第一次执行时,会下载很多文件,大约需要 15 分钟。在操作结束之前不会显示任何反馈。如果我们在 Visual Studio 中执行相同的操作,它会显示正在下载的文件列表。有没有办法在下载文件时在 Powershell 中显示该列表?
  • 您可能需要添加一个“Write-Host”。例如:Write-Host "TFS item to download:" $($item.ServerItem) -ForegroundColor Blu 在这种情况下检查答案:stackoverflow.com/questions/23739499/…
  • 以下载文件方式为例。我正在使用 Get 方法。如何在 Get 方法中写入主机。
  • 我自己测试过,用workspace.get看不到get日志。您可以尝试在脚本中使用tf command 来查看是否可以看到日志。
  • 有没有办法使用 Get 而不是当前时间戳来保存服务器的时间戳?
【解决方案2】:

我能够使用下面的代码示例使用工作区选项获取代码。

if ( (Get-PSSnapin -Name Microsoft.TeamFoundation.PowerShell -ErrorAction SilentlyContinue) -eq $null ) {
     Add-PSSnapin Microsoft.TeamFoundation.PowerShell
    }
    $securePass = ConvertTo-SecureString -AsPlainText -Force -String "mypassword"
    $uri = "https://myserver"
    $cred =  New-Object System.Management.Automation.PSCredential("myusername",$securePass)

$tfsServer = Get-TfsServer -Name $uri -Credential $cred
$structureService = $tfsServer.GetService("Microsoft.TeamFoundation.Server.ICommonStructureService")
$versionControlService = $tfsServer.GetService("Microsoft.TeamFoundation.VersionControl.Client.VersionControlServer")

$workSpaceName = $env:USERNAME + "-IMAG"

$localTFSWorkspace="c:\tfswspace"
$serverRoot = "$/myproject"
$pathsToDownload=[System.Collections.ArrayList]@()
$pathsToDownload.add("$/myproject/path1")
$pathsToDownload.add("$/myproject/path2")

$testPath = $($pathsToDownload[0].Replace($serverRoot,$localTFSWorkspace)).replace("/","\")

if (!(Test-Path $localTFSWorkspace -PathType Container)) {
  New-Item $localTFSWorkspace -ItemType Directory -Force
}

# Check if workspace already exists
     $workspace = $versionControlService.TryGetWorkspace($testPath)
     if ($workspace -eq $null) {
       #Workspace doesn't exist, we need to create one
       $workspace = $versionControlService.CreateWorkspace($workSpaceName,$cred.UserName, 'Workspace for Repository Sync')
     }

 #create mappings if these don't exist 
 foreach ($serverPath in $pathsToDownload) {
      $localPath = $($serverPath.Replace($serverRoot,$localTFSWorkspace)).replace("/","\")
      if (!(Test-Path $localPath -PathType Container)) {
         New-Item $localPath -ItemType Directory -Force
      }

    $workingFolder =  $workspace.TryGetWorkingFolderForServerItem($serverPath)

    if ($workingFolder -eq $null) {
      #create mapping here
      $workspace.Map($serverPath,$localPath)
    }
 }
 # Now mappings are done -- get items now
 $workspace.get()

【讨论】:

    猜你喜欢
    • 2019-03-29
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    • 2014-07-07
    • 2015-05-10
    • 2020-12-06
    • 1970-01-01
    • 2014-10-02
    相关资源
    最近更新 更多