Skip to content

Commit 043f11f

Browse files
committed
Merge pull request #201 from Microsoft/users/tihuang/defaultworkingfolder
set working folder to system.defaultworkingdirectory for node handler.
2 parents f7ce567 + 14fb9a1 commit 043f11f

File tree

7 files changed

+80
-157
lines changed

7 files changed

+80
-157
lines changed

src/Agent.Worker/Build/GitCommandManager.cs

Lines changed: 59 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,15 @@
66
using System.Text.RegularExpressions;
77
using System.Threading;
88
using System.Threading.Tasks;
9+
using System.IO;
910

1011
namespace Microsoft.VisualStudio.Services.Agent.Worker.Build
1112
{
1213
[ServiceLocator(Default = typeof(GitCommandManager))]
1314
public interface IGitCommandManager : IAgentService
1415
{
15-
string GitPath { get; set; }
16-
17-
Version Version { get; set; }
18-
19-
string GitHttpUserAgent { get; set; }
16+
// setup git execution info, git location, version, useragent, execpath
17+
Task LoadGitExecutionInfo(IExecutionContext context);
2018

2119
// git init <LocalDir>
2220
Task<int> GitInit(IExecutionContext context, string repositoryPath);
@@ -56,7 +54,7 @@ public interface IGitCommandManager : IAgentService
5654

5755
// git config --unset-all <key>
5856
Task<int> GitConfigUnset(IExecutionContext context, string repositoryPath, string configKey);
59-
57+
6058
// git config gc.auto 0
6159
Task<int> GitDisableAutoGC(IExecutionContext context, string repositoryPath);
6260

@@ -66,20 +64,36 @@ public interface IGitCommandManager : IAgentService
6664

6765
public class GitCommandManager : AgentService, IGitCommandManager
6866
{
69-
private readonly Dictionary<string, Dictionary<Version, string>> _gitCommands = new Dictionary<string, Dictionary<Version, string>>(StringComparer.OrdinalIgnoreCase)
67+
private string _gitHttpUserAgentEnv = null;
68+
private string _gitPath = null;
69+
private Version _version = null;
70+
private string _gitExecPathEnv = null;
71+
72+
public async Task LoadGitExecutionInfo(IExecutionContext context)
7073
{
74+
#if OS_WINDOWS
75+
_gitPath = Path.Combine(IOUtil.GetExternalsPath(), "git", "cmd", $"git{IOUtil.ExeExtension}");
76+
#else
77+
_gitPath = Path.Combine(IOUtil.GetExternalsPath(), "git", "bin", $"git{IOUtil.ExeExtension}");
78+
#endif
79+
if (string.IsNullOrEmpty(_gitPath) || !File.Exists(_gitPath))
7180
{
72-
"checkout", new Dictionary<Version, string> ()
73-
{
74-
{ new Version(1,8), "--force {0}" },
75-
{ new Version(2,7), "--progress --force {0}" }
76-
}
81+
throw new Exception(StringUtil.Loc("GitNotFound"));
7782
}
78-
};
7983

80-
public string GitPath { get; set; }
81-
public Version Version { get; set; }
82-
public string GitHttpUserAgent { get; set; }
84+
context.Debug($"Find git from agent's external directory: {_gitPath}.");
85+
86+
_version = await GitVersion(context);
87+
context.Debug($"Detect git version: {_version.ToString()}.");
88+
89+
_gitHttpUserAgentEnv = $"git/{_version.ToString()} (vsts-agent-git/{Constants.Agent.Version})";
90+
context.Debug($"Set git useragent to: {_gitHttpUserAgentEnv}.");
91+
92+
#if !OS_WINDOWS
93+
_gitExecPathEnv = Path.Combine(IOUtil.GetExternalsPath(), "git", "libexec", "git-core");
94+
context.Debug($"Set git execpath to: {_gitExecPathEnv}");
95+
#endif
96+
}
8397

8498
// git init <LocalDir>
8599
public async Task<int> GitInit(IExecutionContext context, string repositoryPath)
@@ -105,8 +119,7 @@ public async Task<int> GitFetch(IExecutionContext context, string repositoryPath
105119
public async Task<int> GitCheckout(IExecutionContext context, string repositoryPath, string committishOrBranchSpec, CancellationToken cancellationToken)
106120
{
107121
context.Debug($"Checkout {committishOrBranchSpec}.");
108-
string checkoutOption = GetCommandOption("checkout");
109-
return await ExecuteGitCommandAsync(context, repositoryPath, "checkout", StringUtil.Format(checkoutOption, committishOrBranchSpec), cancellationToken);
122+
return await ExecuteGitCommandAsync(context, repositoryPath, "checkout", StringUtil.Format("--progress --force {0}", committishOrBranchSpec), cancellationToken);
110123
}
111124

112125
// git clean -fdx
@@ -225,6 +238,7 @@ public async Task<Version> GitVersion(IExecutionContext context)
225238
Version version = null;
226239
List<string> outputStrings = new List<string>();
227240
int exitCode = await ExecuteGitCommandAsync(context, IOUtil.GetWorkPath(HostContext), "version", null, outputStrings);
241+
context.Debug($"git version ouput: {string.Join(Environment.NewLine, outputStrings)}");
228242
if (exitCode == 0)
229243
{
230244
// remove any empty line.
@@ -248,32 +262,6 @@ public async Task<Version> GitVersion(IExecutionContext context)
248262
return version;
249263
}
250264

251-
private string GetCommandOption(string command)
252-
{
253-
if (string.IsNullOrEmpty(command))
254-
{
255-
throw new ArgumentNullException("command");
256-
}
257-
258-
if (!_gitCommands.ContainsKey(command))
259-
{
260-
throw new NotSupportedException($"Unsupported git command: {command}");
261-
}
262-
263-
Dictionary<Version, string> options = _gitCommands[command];
264-
foreach (var versionOption in options.OrderByDescending(o => o.Key))
265-
{
266-
if (Version >= versionOption.Key)
267-
{
268-
return versionOption.Value;
269-
}
270-
}
271-
272-
var earliestVersion = options.OrderByDescending(o => o.Key).Last();
273-
Trace.Info($"Fallback to version {earliestVersion.Key.ToString()} command option for git {command}.");
274-
return earliestVersion.Value;
275-
}
276-
277265
private async Task<int> ExecuteGitCommandAsync(IExecutionContext context, string repoRoot, string command, string options, CancellationToken cancellationToken = default(CancellationToken))
278266
{
279267
string arg = StringUtil.Format($"{command} {options}").Trim();
@@ -290,13 +278,18 @@ private string GetCommandOption(string command)
290278
context.Output(message.Data);
291279
};
292280

293-
Dictionary<string, string> _userAgentEnv = new Dictionary<string, string>();
294-
if (!string.IsNullOrEmpty(GitHttpUserAgent))
281+
Dictionary<string, string> _gitEnv = new Dictionary<string, string>();
282+
if (!string.IsNullOrEmpty(_gitHttpUserAgentEnv))
295283
{
296-
_userAgentEnv["GIT_HTTP_USER_AGENT"] = GitHttpUserAgent;
284+
_gitEnv["GIT_HTTP_USER_AGENT"] = _gitHttpUserAgentEnv;
297285
}
298286

299-
return await processInvoker.ExecuteAsync(repoRoot, GitPath, arg, _userAgentEnv, cancellationToken);
287+
if (!string.IsNullOrEmpty(_gitExecPathEnv))
288+
{
289+
_gitEnv["GIT_EXEC_PATH"] = _gitExecPathEnv;
290+
}
291+
292+
return await processInvoker.ExecuteAsync(repoRoot, _gitPath, arg, _gitEnv, cancellationToken);
300293
}
301294

302295
private async Task<int> ExecuteGitCommandAsync(IExecutionContext context, string repoRoot, string command, string options, IList<string> output)
@@ -327,13 +320,18 @@ private async Task<int> ExecuteGitCommandAsync(IExecutionContext context, string
327320
}
328321
};
329322

330-
Dictionary<string, string> _userAgentEnv = new Dictionary<string, string>();
331-
if (!string.IsNullOrEmpty(GitHttpUserAgent))
323+
Dictionary<string, string> _gitEnv = new Dictionary<string, string>();
324+
if (!string.IsNullOrEmpty(_gitHttpUserAgentEnv))
325+
{
326+
_gitEnv["GIT_HTTP_USER_AGENT"] = _gitHttpUserAgentEnv;
327+
}
328+
329+
if (!string.IsNullOrEmpty(_gitExecPathEnv))
332330
{
333-
_userAgentEnv["GIT_HTTP_USER_AGENT"] = GitHttpUserAgent;
331+
_gitEnv["GIT_EXEC_PATH"] = _gitExecPathEnv;
334332
}
335333

336-
return await processInvoker.ExecuteAsync(repoRoot, GitPath, arg, _userAgentEnv, default(CancellationToken));
334+
return await processInvoker.ExecuteAsync(repoRoot, _gitPath, arg, _gitEnv, default(CancellationToken));
337335
}
338336

339337
private async Task<int> ExecuteGitCommandAsync(IExecutionContext context, string repoRoot, string command, string options, string additionalCommandLine, CancellationToken cancellationToken)
@@ -352,13 +350,18 @@ private async Task<int> ExecuteGitCommandAsync(IExecutionContext context, string
352350
context.Output(message.Data);
353351
};
354352

355-
Dictionary<string, string> _userAgentEnv = new Dictionary<string, string>();
356-
if (!string.IsNullOrEmpty(GitHttpUserAgent))
353+
Dictionary<string, string> _gitEnv = new Dictionary<string, string>();
354+
if (!string.IsNullOrEmpty(_gitHttpUserAgentEnv))
355+
{
356+
_gitEnv["GIT_HTTP_USER_AGENT"] = _gitHttpUserAgentEnv;
357+
}
358+
359+
if (!string.IsNullOrEmpty(_gitExecPathEnv))
357360
{
358-
_userAgentEnv["GIT_HTTP_USER_AGENT"] = GitHttpUserAgent;
361+
_gitEnv["GIT_EXEC_PATH"] = _gitExecPathEnv;
359362
}
360363

361-
return await processInvoker.ExecuteAsync(repoRoot, GitPath, arg, _userAgentEnv, cancellationToken);
364+
return await processInvoker.ExecuteAsync(repoRoot, _gitPath, arg, _gitEnv, cancellationToken);
362365
}
363366
}
364367
}

src/Agent.Worker/Build/GitSourceProvider.cs

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public virtual async Task GetSourceAsync(IExecutionContext executionContext, Ser
3131
ArgUtil.NotNull(endpoint, nameof(endpoint));
3232

3333
executionContext.Output($"Syncing repository: {endpoint.Name} (Git)");
34+
_gitCommandManager = HostContext.GetService<IGitCommandManager>();
35+
await _gitCommandManager.LoadGitExecutionInfo(executionContext);
3436

3537
string targetPath = executionContext.Variables.Get(Constants.Variables.Build.SourcesDirectory);
3638
string sourceBranch = executionContext.Variables.Get(Constants.Variables.Build.SourceBranch);
@@ -58,29 +60,6 @@ public virtual async Task GetSourceAsync(IExecutionContext executionContext, Ser
5860
Trace.Info($"checkoutSubmodules={checkoutSubmodules}");
5961
Trace.Info($"exposeCred={exposeCred}");
6062

61-
// ensure find full path to git exist, the version of the installed git is what we supported.
62-
string gitPath = null;
63-
if (!TryGetGitLocation(executionContext, out gitPath))
64-
{
65-
throw new Exception(StringUtil.Loc("GitNotInstalled"));
66-
}
67-
Trace.Info($"Git path={gitPath}");
68-
69-
_gitCommandManager = HostContext.GetService<IGitCommandManager>();
70-
_gitCommandManager.GitPath = gitPath;
71-
72-
Version gitVersion = await _gitCommandManager.GitVersion(executionContext);
73-
if (gitVersion < _minSupportGitVersion)
74-
{
75-
throw new Exception(StringUtil.Loc("InstalledGitNotSupport", _minSupportGitVersion));
76-
}
77-
Trace.Info($"Git version={gitVersion}");
78-
_gitCommandManager.Version = gitVersion;
79-
80-
string customizeUserAgent = $"git/{gitVersion.ToString()} (vsts-agent-git/{Constants.Agent.Version})";
81-
Trace.Info($"Git useragent={customizeUserAgent}");
82-
_gitCommandManager.GitHttpUserAgent = customizeUserAgent;
83-
8463
// retrieve credential from endpoint.
8564
Uri repositoryUrl = endpoint.Url;
8665
if (!repositoryUrl.IsAbsoluteUri)
@@ -309,38 +288,6 @@ public virtual async Task PostJobCleanupAsync(IExecutionContext executionContext
309288
await RemoveCachedCredential(executionContext, targetPath, repositoryUrl, "origin");
310289
}
311290

312-
private bool TryGetGitLocation(IExecutionContext executionContext, out string gitPath)
313-
{
314-
//find git in %Path%
315-
var whichTool = HostContext.GetService<IWhichUtil>();
316-
gitPath = whichTool.Which("git");
317-
318-
#if OS_WINDOWS
319-
//find in %ProgramFiles(x86)%\git\cmd if platform is Windows
320-
if (string.IsNullOrEmpty(gitPath))
321-
{
322-
string programFileX86 = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
323-
if (!string.IsNullOrEmpty(programFileX86))
324-
{
325-
gitPath = Path.Combine(programFileX86, "Git\\cmd\\git.exe");
326-
if (!File.Exists(gitPath))
327-
{
328-
gitPath = null;
329-
}
330-
}
331-
}
332-
#endif
333-
if (string.IsNullOrEmpty(gitPath))
334-
{
335-
return false;
336-
}
337-
else
338-
{
339-
executionContext.Debug($"Find git installation path: {gitPath}.");
340-
return true;
341-
}
342-
}
343-
344291
protected async Task<bool> IsRepositoryOriginUrlMatch(IExecutionContext context, string repositoryPath, Uri expectedRepositoryOriginUrl)
345292
{
346293
context.Debug($"Checking if the repo on {repositoryPath} matches the expected repository origin URL. expected Url: {expectedRepositoryOriginUrl.AbsoluteUri}");

src/Agent.Worker/Build/TfsGitSourceProvider.cs

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,17 @@ namespace Microsoft.VisualStudio.Services.Agent.Worker.Build
1212
{
1313
public sealed class TfsGitSourceProvider : GitSourceProvider, ISourceProvider
1414
{
15-
public override string RepositoryType => WellKnownRepositoryTypes.TfsGit;
1615
private readonly Dictionary<string, string> _authHeaderCache = new Dictionary<string, string>();
17-
private bool _supportAddAuthHeader = false;
16+
17+
public override string RepositoryType => WellKnownRepositoryTypes.TfsGit;
1818

1919
public override async Task GetSourceAsync(IExecutionContext executionContext, ServiceEndpoint endpoint, CancellationToken cancellationToken)
2020
{
2121
Trace.Entering();
2222
ArgUtil.NotNull(endpoint, nameof(endpoint));
23-
24-
string gitPath = null;
25-
_supportAddAuthHeader = IsLocalGitSupportAddAuthHeader(out gitPath);
26-
if (!_supportAddAuthHeader)
27-
{
28-
// use default git source provider handle credential which will embed credential into remote url
29-
await base.GetSourceAsync(executionContext, endpoint, cancellationToken);
30-
return;
31-
}
32-
3323
executionContext.Output($"Syncing repository: {endpoint.Name} (TfsGit)");
24+
_gitCommandManager = HostContext.GetService<IGitCommandManager>();
25+
await _gitCommandManager.LoadGitExecutionInfo(executionContext);
3426

3527
string targetPath = executionContext.Variables.Get(Constants.Variables.Build.SourcesDirectory);
3628
string sourceBranch = executionContext.Variables.Get(Constants.Variables.Build.SourceBranch);
@@ -57,18 +49,6 @@ public override async Task GetSourceAsync(IExecutionContext executionContext, Se
5749
Trace.Info($"clean={clean}");
5850
Trace.Info($"checkoutSubmodules={checkoutSubmodules}");
5951
Trace.Info($"exposeCred={exposeCred}");
60-
Trace.Info($"Git path={gitPath}");
61-
62-
_gitCommandManager = HostContext.GetService<IGitCommandManager>();
63-
_gitCommandManager.GitPath = gitPath;
64-
65-
Version gitVersion = await _gitCommandManager.GitVersion(executionContext);
66-
Trace.Info($"Git version={gitVersion}");
67-
_gitCommandManager.Version = gitVersion;
68-
69-
string customizeUserAgent = $"git/{gitVersion.ToString()} (vsts-agent-git/{Constants.Agent.Version})";
70-
Trace.Info($"Git useragent={customizeUserAgent}");
71-
_gitCommandManager.GitHttpUserAgent = customizeUserAgent;
7252

7353
// retrieve credential from endpoint.
7454
Uri repositoryUrl = endpoint.Url;
@@ -261,15 +241,9 @@ public override async Task GetSourceAsync(IExecutionContext executionContext, Se
261241
public override async Task PostJobCleanupAsync(IExecutionContext executionContext, ServiceEndpoint endpoint)
262242
{
263243
Trace.Entering();
264-
if (!_supportAddAuthHeader)
265-
{
266-
await base.PostJobCleanupAsync(executionContext, endpoint);
267-
return;
268-
}
269-
270244
ArgUtil.NotNull(endpoint, nameof(endpoint));
271245
executionContext.Output($"Cleaning extra http auth header from repository: {endpoint.Name} (TfsGit)");
272-
246+
273247
Uri repositoryUrl = endpoint.Url;
274248
string targetPath = executionContext.Variables.Get(Constants.Variables.Build.SourcesDirectory);
275249

@@ -298,18 +272,5 @@ public override async Task PostJobCleanupAsync(IExecutionContext executionContex
298272
}
299273
}
300274
}
301-
302-
private bool IsLocalGitSupportAddAuthHeader(out string gitPath)
303-
{
304-
gitPath = string.Empty;
305-
306-
// find portable git in externals
307-
#if OS_WINDOWS
308-
gitPath = Path.Combine(IOUtil.GetExternalsPath(), "git", "cmd", $"git{IOUtil.ExeExtension}");
309-
#else
310-
gitPath = Path.Combine(IOUtil.GetExternalsPath(), "git", "bin", $"git{IOUtil.ExeExtension}");
311-
#endif
312-
return !string.IsNullOrEmpty(gitPath) && File.Exists(gitPath);
313-
}
314275
}
315276
}

src/Agent.Worker/Handlers/NodeHandler.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,14 @@ public async Task RunAsync()
4343
string workingDirectory = Data.WorkingDirectory;
4444
if (string.IsNullOrEmpty(workingDirectory))
4545
{
46-
workingDirectory = TaskDirectory;
46+
if (!string.IsNullOrEmpty(ExecutionContext.Variables.System_DefaultWorkingDirectory))
47+
{
48+
workingDirectory = ExecutionContext.Variables.System_DefaultWorkingDirectory;
49+
}
50+
else
51+
{
52+
workingDirectory = ExecutionContext.Variables.Agent_WorkFolder;
53+
}
4754
}
4855

4956
ArgUtil.Directory(workingDirectory, nameof(workingDirectory));

src/Agent.Worker/Variables.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ into maskHintGrouping
8787
}
8888

8989
public string Agent_BuildDirectory { get { return Get(Constants.Variables.Agent.BuildDirectory); } }
90+
public string Agent_WorkFolder { get { return Get(Constants.Variables.Agent.WorkFolder); } }
9091
public TaskResult? Agent_JobStatus { get { return GetEnum<TaskResult>(Constants.Variables.Agent.JobStatus); } set { Set(Constants.Variables.Agent.JobStatus, $"{value}"); } }
9192
public int? Build_BuildId { get { return GetInt(BuildWebApi.WellKnownBuildVariables.BuildId); } }
9293
public string Build_BuildUri { get { return Get(BuildWebApi.WellKnownBuildVariables.BuildUri); } }
@@ -107,6 +108,7 @@ into maskHintGrouping
107108
public string Release_ReleaseUri { get { return Get(Constants.Variables.Release.ReleaseUri); } }
108109
public string System_CollectionId { get { return Get(Constants.Variables.System.CollectionId); } }
109110
public bool? System_Debug { get { return GetBoolean(Constants.Variables.System.Debug); } }
111+
public string System_DefaultWorkingDirectory { get { return Get(Constants.Variables.System.DefaultWorkingDirectory); } }
110112
public string System_DefinitionId { get { return Get(Constants.Variables.System.DefinitionId); } }
111113
public bool? System_EnableAccessToken { get { return GetBoolean(Constants.Variables.System.EnableAccessToken); } }
112114
public string System_HostType { get { return Get(Constants.Variables.System.HostType); } }

0 commit comments

Comments
 (0)