Here are the examples of the csharp api System.Threading.CancellationToken.ThrowIfCancellationRequested() taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.
5532 Examples
19
View Source File : ExpandableBufferWriter.cs
License : MIT License
Project Creator : 1996v
License : MIT License
Project Creator : 1996v
public async Task CopyToAsync(Stream stream, CancellationToken CancellationToken)
{
if (Buffered > 0)
{
FlushLastSpanBoundary();
for (int i = 0; i < complexBuffer.Spans.Length; i++)
{
if (bufferedsRelativeSpan[i] != 0)
{
CancellationToken.ThrowIfCancellationRequested();
await complexBuffer.Spans[i].WriteToAsync(stream, bufferedsRelativeSpan[i]).ConfigureAwait(false);
}
}
}
}
19
View Source File : ExpandableBufferWriter.cs
License : MIT License
Project Creator : 1996v
License : MIT License
Project Creator : 1996v
public void CopyTo(Stream stream, CancellationToken CancellationToken)
{
if (Buffered > 0)
{
FlushLastSpanBoundary();
for (int i = 0; i < complexBuffer.Spans.Length; i++)
{
if (bufferedsRelativeSpan[i] != 0)
{
CancellationToken.ThrowIfCancellationRequested();
complexBuffer.Spans[i].WriteTo(stream, bufferedsRelativeSpan[i]);
}
}
}
}
19
View Source File : CSRedisCache.cs
License : MIT License
Project Creator : 2881099
License : MIT License
Project Creator : 2881099
public async Task<byte[]> GetAsync(string key, CancellationToken token = default(CancellationToken)) {
if (key == null) {
throw new ArgumentNullException(nameof(key));
}
token.ThrowIfCancellationRequested();
return await GetAndRefreshAsync(key, getData: true, token: token);
}
19
View Source File : CSRedisCache.cs
License : MIT License
Project Creator : 2881099
License : MIT License
Project Creator : 2881099
public async Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = default(CancellationToken)) {
if (key == null) {
throw new ArgumentNullException(nameof(key));
}
if (value == null) {
throw new ArgumentNullException(nameof(value));
}
if (options == null) {
throw new ArgumentNullException(nameof(options));
}
token.ThrowIfCancellationRequested();
var creationTime = DateTimeOffset.UtcNow;
var absoluteExpiration = GetAbsoluteExpiration(creationTime, options);
await _redisClient.EvalAsync(SetScript, key,
new object[]
{
absoluteExpiration?.Ticks ?? NotPresent,
options.SlidingExpiration?.Ticks ?? NotPresent,
GetExpirationInSeconds(creationTime, absoluteExpiration, options) ?? NotPresent,
value
});
}
19
View Source File : CSRedisCache.cs
License : MIT License
Project Creator : 2881099
License : MIT License
Project Creator : 2881099
private async Task RefreshAsync(string key, DateTimeOffset? absExpr, TimeSpan? sldExpr, CancellationToken token = default(CancellationToken)) {
if (key == null) {
throw new ArgumentNullException(nameof(key));
}
token.ThrowIfCancellationRequested();
// Note Refresh has no effect if there is just an absolute expiration (or neither).
TimeSpan? expr = null;
if (sldExpr.HasValue) {
if (absExpr.HasValue) {
var relExpr = absExpr.Value - DateTimeOffset.Now;
expr = relExpr <= sldExpr.Value ? relExpr : sldExpr;
} else {
expr = sldExpr;
}
await _redisClient.ExpireAsync(key, expr ?? TimeSpan.Zero);
// TODO: Error handling
}
}
19
View Source File : CSRedisCache.cs
License : MIT License
Project Creator : 2881099
License : MIT License
Project Creator : 2881099
public async Task RefreshAsync(string key, CancellationToken token = default(CancellationToken)) {
if (key == null) {
throw new ArgumentNullException(nameof(key));
}
token.ThrowIfCancellationRequested();
await GetAndRefreshAsync(key, getData: false, token: token);
}
19
View Source File : CSRedisCache.cs
License : MIT License
Project Creator : 2881099
License : MIT License
Project Creator : 2881099
private async Task<byte[]> GetAndRefreshAsync(string key, bool getData, CancellationToken token = default(CancellationToken)) {
if (key == null) {
throw new ArgumentNullException(nameof(key));
}
token.ThrowIfCancellationRequested();
// This also resets the LRU status as desired.
// TODO: Can this be done in one operation on the server side? Probably, the trick would just be the DateTimeOffset math.
object[] results;
byte[] value = null;
if (getData) {
var ret = await _redisClient.HMGetAsync<byte[]>(key, AbsoluteExpirationKey, SlidingExpirationKey, DataKey);
results = new object[] { ret[0] == null ? null : Encoding.UTF8.GetString(ret[0]), ret[1] == null ? null : Encoding.UTF8.GetString(ret[1]), value = ret[2] };
} else {
results = await _redisClient.HMGetAsync(key, AbsoluteExpirationKey, SlidingExpirationKey);
}
// TODO: Error handling
if (results.Length >= 2) {
MapMetadata(results, out DateTimeOffset? absExpr, out TimeSpan? sldExpr);
await RefreshAsync(key, absExpr, sldExpr, token);
}
if (results.Length >= 3) {
return value;
}
return null;
}
19
View Source File : RtmpServer.cs
License : MIT License
Project Creator : a1q123456
License : MIT License
Project Creator : a1q123456
public Task StartAsync(CancellationToken ct = default)
{
if (Started)
{
throw new InvalidOperationException("already started");
}
_webSocketServer?.Start(c =>
{
var session = new WebSocketSession(c, _webSocketOptions);
c.OnOpen = session.HandleOpen;
c.OnClose = session.HandleClose;
c.OnMessage = session.HandleMessage;
});
if (_webSocketServer != null)
{
CancellationTokenRegistration reg = default;
reg = ct.Register(() =>
{
reg.Dispose();
_webSocketServer.Dispose();
_webSocketServer = new WebSocketServer(_webSocketOptions.BindEndPoint.ToString());
});
}
Started = true;
var ret = new TaskCompletionSource<int>();
var t = new Thread(o =>
{
try
{
while (!ct.IsCancellationRequested)
{
try
{
_allDone.Reset();
_listener.BeginAccept(new AsyncCallback(ar =>
{
AcceptCallback(ar, ct);
}), _listener);
while (!_allDone.WaitOne(1))
{
ct.ThrowIfCancellationRequested();
}
}
catch (OperationCanceledException)
{
throw;
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
catch (OperationCanceledException) { }
finally
{
ret.SetResult(1);
}
});
t.Start();
return ret.Task;
}
19
View Source File : Supervisor.cs
License : MIT License
Project Creator : a1q123456
License : MIT License
Project Creator : a1q123456
private void ThreadEntry()
{
try
{
while (!cancellationToken.IsCancellationRequested)
{
cancellationToken.ThrowIfCancellationRequested();
foreach (var kv in server.connectedSessions)
{
if (!sessionStates.TryGetValue(kv.Key, out var sessionState))
{
sessionState = new SessionState()
{
LastPing = DateTime.Now,
Session = kv.Value
};
sessionStates.Add(kv.Key, sessionState);
}
var session = kv.Value;
if (DateTime.Now - sessionState.LastPing >= pingInterval && sessionState.CancellationTokenSource == null)
{
sessionState.CancellationTokenSource = new CancellationTokenSource();
sessionState.CancellationTokenSource.CancelAfter((int)responseThreshole.TotalMilliseconds);
var pingTask = session.PingAsync(sessionState.CancellationTokenSource.Token);
pingTask.ContinueWith(tsk =>
{
sessionState.CancellationTokenSource.Dispose();
sessionState.CancellationTokenSource = null;
sessionState.LastPing = DateTime.Now;
}, TaskContinuationOptions.OnlyOnRanToCompletion);
pingTask.ContinueWith(tsk =>
{
sessionState.Session.Disconnect(new ExceptionalEventArgs("pingpong timeout"));
sessionState.CancellationTokenSource.Dispose();
sessionState.CancellationTokenSource = null;
}, TaskContinuationOptions.OnlyOnCanceled);
}
}
Thread.Sleep(1);
cancellationToken.ThrowIfCancellationRequested();
}
}
catch
{
}
}
19
View Source File : StreamHelper.cs
License : MIT License
Project Creator : a1q123456
License : MIT License
Project Creator : a1q123456
public static async Task ReadBytesAsync(this Stream stream, Memory<byte> buffer, CancellationToken ct = default)
{
int count = buffer.Length;
var offset = 0;
while (count != 0)
{
var n = await stream.ReadAsync(buffer.Slice(offset, count), ct);
ct.ThrowIfCancellationRequested();
if (n == 0)
{
break;
}
offset += n;
count -= n;
}
if (offset != buffer.Length)
{
throw new EndOfStreamException();
}
}
19
View Source File : TaskHelpers.cs
License : MIT License
Project Creator : abdullin
License : MIT License
Project Creator : abdullin
public static Func<TSource, CancellationToken, TResult> WithCancellation<TSource, TResult>([NotNull] Func<TSource, TResult> lambda)
{
Contract.Requires(lambda != null);
return (value, ct) =>
{
if (ct.IsCancellationRequested) ct.ThrowIfCancellationRequested();
return lambda(value);
};
}
19
View Source File : MixedRealityToolkitFiles.cs
License : Apache License 2.0
Project Creator : abist-co-ltd
License : Apache License 2.0
Project Creator : abist-co-ltd
private static void SearchForFolders(string rootPath, CancellationToken ct)
{
try
{
var filePathResults = Directory.GetFiles(rootPath, SentinelFilePattern, SearchOption.AllDirectories);
foreach (var sentinelFilePath in filePathResults)
{
TryRegisterModuleViaFile(sentinelFilePath);
if (ct.IsCancellationRequested)
{
ct.ThrowIfCancellationRequested();
}
}
// Create the Generated folder, if the user tries to delete the Generated folder it will be created again
TryToCreateGeneratedFolder();
}
catch (OperationCanceledException)
{
Console.WriteLine($"\n{nameof(OperationCanceledException)} thrown\n");
}
catch (Exception ex)
{
Debug.LogError(ex.Message);
}
}
19
View Source File : CategoryTreeBuilder.cs
License : Apache License 2.0
Project Creator : acblog
License : Apache License 2.0
Project Creator : acblog
public static async Task<(CategoryTree, IReadOnlyDictionary<CategoryTree.CategoryTreeNode, IList<Post>>)> BuildFromPosts(IAsyncEnumerable<Post> data, CancellationToken cancellationToken = default)
{
CategoryTree.CategoryTreeNode root = new CategoryTree.CategoryTreeNode(new Category());
Dictionary<CategoryTree.CategoryTreeNode, IList<Post>> map = new Dictionary<CategoryTree.CategoryTreeNode, IList<Post>>();
await foreach (var v in data)
{
cancellationToken.ThrowIfCancellationRequested();
CategoryTree.CategoryTreeNode node = root;
foreach (var k in v.Category.Items)
{
if (!node.Children.ContainsKey(k))
{
CategoryBuilder cb = new CategoryBuilder();
cb.AddSubCategory(node.Category.Items.Concat(new[] { k }).ToArray());
Category c = cb.Build();
var tn = new CategoryTree.CategoryTreeNode(c);
map.Add(tn, new List<Post>());
node.Children.Add(k, tn);
node = tn;
}
else
{
node = node.Children[k];
}
map[node].Add(v);
}
}
return (new CategoryTree(root), map);
}
19
View Source File : CategoryTreeBuilder.cs
License : Apache License 2.0
Project Creator : acblog
License : Apache License 2.0
Project Creator : acblog
public static async Task<CategoryTree> Build(IAsyncEnumerable<Category> data, CancellationToken cancellationToken = default)
{
CategoryTree.CategoryTreeNode root = new CategoryTree.CategoryTreeNode(new Category());
await foreach (var v in data)
{
cancellationToken.ThrowIfCancellationRequested();
CategoryTree.CategoryTreeNode node = root;
foreach (var k in v.Items)
{
if (!node.Children.ContainsKey(k))
{
CategoryBuilder cb = new CategoryBuilder();
cb.AddSubCategory(node.Category.Items.Concat(new[] { k }).ToArray());
Category c = cb.Build();
var tn = new CategoryTree.CategoryTreeNode(c);
node.Children.Add(k, tn);
node = tn;
}
else
{
node = node.Children[k];
}
}
}
return new CategoryTree(root);
}
19
View Source File : KeywordCollectionBuilder.cs
License : Apache License 2.0
Project Creator : acblog
License : Apache License 2.0
Project Creator : acblog
public static async Task<(KeywordCollection, IReadOnlyDictionary<string, IList<Post>>)> BuildFromPosts(IAsyncEnumerable<Post> data, CancellationToken cancellationToken = default)
{
Dictionary<string, IList<Post>> dict = new Dictionary<string, IList<Post>>();
await foreach (var v in data)
{
cancellationToken.ThrowIfCancellationRequested();
List<string> keyids = new List<string>();
foreach (var k in v.Keywords.Items)
{
if (!dict.ContainsKey(k))
{
var list = new List<Post>
{
v
};
dict.Add(k, list);
}
else
{
dict[k].Add(v);
}
}
}
return (new KeywordCollection(dict.Select(pair => new Keyword { Items = new string[] { pair.Key } }).ToList()), dict);
}
19
View Source File : KeywordCollectionBuilder.cs
License : Apache License 2.0
Project Creator : acblog
License : Apache License 2.0
Project Creator : acblog
public static async Task<KeywordCollection> Build(IAsyncEnumerable<Keyword> data, CancellationToken cancellationToken = default)
{
HashSet<string> res = new HashSet<string>();
await foreach (var v in data)
{
cancellationToken.ThrowIfCancellationRequested();
List<string> keyids = new List<string>();
foreach (var k in v.Items)
{
res.Add(k);
}
}
return new KeywordCollection(res.Select(pair => new Keyword { Items = new string[] { pair } }).ToList());
}
19
View Source File : FunctionalExtensions.cs
License : MIT License
Project Creator : Accelerider
License : MIT License
Project Creator : Accelerider
public static Func<TInput, Task<T>> ThenAsync<TInput, TOutput, T>(
this Func<TInput, Task<TOutput>> @this,
Func<TOutput, T> function,
CancellationToken cancellationToken = default)
{
ThrowIfNull(function);
return async input =>
{
cancellationToken.ThrowIfCancellationRequested();
var output = await @this(input);
return function(output);
};
}
19
View Source File : FunctionalExtensions.cs
License : MIT License
Project Creator : Accelerider
License : MIT License
Project Creator : Accelerider
public static Func<TInput, Task<IEnumerable<T>>> ThenAsync<TInput, TOutput, T>(
this Func<TInput, Task<IEnumerable<TOutput>>> @this,
Func<TOutput, T> function,
CancellationToken cancellationToken = default)
{
ThrowIfNull(function);
return async input =>
{
cancellationToken.ThrowIfCancellationRequested();
var output = await @this(input);
return output.Select(item =>
{
cancellationToken.ThrowIfCancellationRequested();
return function(item);
});
};
}
19
View Source File : FunctionalExtensions.cs
License : MIT License
Project Creator : Accelerider
License : MIT License
Project Creator : Accelerider
public static Func<TInput, Task<T>> ThenAsync<TInput, TOutput, T>(
this Func<TInput, Task<TOutput>> @this,
Func<TOutput, Task<T>> function,
CancellationToken cancellationToken = default)
{
ThrowIfNull(function);
return async input =>
{
cancellationToken.ThrowIfCancellationRequested();
var output = await @this(input);
return await function(output);
};
}
19
View Source File : FunctionalExtensions.cs
License : MIT License
Project Creator : Accelerider
License : MIT License
Project Creator : Accelerider
public static Func<TInput, Task<IEnumerable<T>>> ThenAsync<TInput, TOutput, T>(
this Func<TInput, Task<IEnumerable<TOutput>>> @this,
Func<TOutput, Task<T>> function,
CancellationToken cancellationToken = default)
{
ThrowIfNull(function);
return async input =>
{
cancellationToken.ThrowIfCancellationRequested();
var output = await @this(input);
var result = new List<T>();
foreach (var item in output)
{
cancellationToken.ThrowIfCancellationRequested();
result.Add(await function(item));
}
return result;
};
}
19
View Source File : RecordFSRepo.cs
License : Apache License 2.0
Project Creator : acblog
License : Apache License 2.0
Project Creator : acblog
public override IAsyncEnumerable<string> All(CancellationToken cancellationToken = default)
{
IEnumerable<string> Inner()
{
foreach (var file in Directory.EnumerateFiles(RootPath, "*.md", SearchOption.AllDirectories))
{
cancellationToken.ThrowIfCancellationRequested();
var name = Path.GetRelativePath(RootPath, file);
yield return name[0..^3].Replace('\\', '/');
}
}
return Inner().ToAsyncEnumerable();
}
19
View Source File : MessageListener.cs
License : MIT License
Project Creator : actions
License : MIT License
Project Creator : actions
public async Task<Boolean> CreateSessionAsync(CancellationToken token)
{
Trace.Entering();
// Settings
var configManager = HostContext.GetService<IConfigurationManager>();
_settings = configManager.LoadSettings();
var serverUrl = _settings.ServerUrl;
Trace.Info(_settings);
// Create connection.
Trace.Info("Loading Credentials");
var credMgr = HostContext.GetService<ICredentialManager>();
VssCredentials creds = credMgr.LoadCredentials();
var agent = new TaskAgentReference
{
Id = _settings.AgentId,
Name = _settings.AgentName,
Version = BuildConstants.RunnerPackage.Version,
OSDescription = RuntimeInformation.OSDescription,
};
string sessionName = $"{Environment.MachineName ?? "RUNNER"}";
var taskAgentSession = new TaskAgentSession(sessionName, agent);
string errorMessage = string.Empty;
bool encounteringError = false;
while (true)
{
token.ThrowIfCancellationRequested();
Trace.Info($"Attempt to create session.");
try
{
Trace.Info("Connecting to the Runner Server...");
await _runnerServer.ConnectAsync(new Uri(serverUrl), creds);
Trace.Info("VssConnection created");
_term.WriteLine();
_term.WriteSuccessMessage("Connected to GitHub");
_term.WriteLine();
_session = await _runnerServer.CreateAgentSessionAsync(
_settings.PoolId,
taskAgentSession,
token);
Trace.Info($"Session created.");
if (encounteringError)
{
_term.WriteLine($"{DateTime.UtcNow:u}: Runner reconnected.");
_sessionCreationExceptionTracker.Clear();
encounteringError = false;
}
return true;
}
catch (OperationCanceledException) when (token.IsCancellationRequested)
{
Trace.Info("Session creation has been cancelled.");
throw;
}
catch (TaskAgentAccessTokenExpiredException)
{
Trace.Info("Runner OAuth token has been revoked. Session creation failed.");
throw;
}
catch (Exception ex)
{
Trace.Error("Catch exception during create session.");
Trace.Error(ex);
if (ex is VssOAuthTokenRequestException && creds.Federated is VssOAuthCredential vssOAuthCred)
{
// Check whether we get 401 because the runner registration already removed by the service.
// If the runner registration get deleted, we can't exchange oauth token.
Trace.Error("Test oauth app registration.");
var oauthTokenProvider = new VssOAuthTokenProvider(vssOAuthCred, new Uri(serverUrl));
var authError = await oauthTokenProvider.ValidateCredentialAsync(token);
if (string.Equals(authError, "invalid_client", StringComparison.OrdinalIgnoreCase))
{
_term.WriteError("Failed to create a session. The runner registration has been deleted from the server, please re-configure.");
return false;
}
}
if (!IsSessionCreationExceptionRetriable(ex))
{
_term.WriteError($"Failed to create session. {ex.Message}");
return false;
}
if (!encounteringError) //print the message only on the first error
{
_term.WriteError($"{DateTime.UtcNow:u}: Runner connect error: {ex.Message}. Retrying until reconnected.");
encounteringError = true;
}
Trace.Info("Sleeping for {0} seconds before retrying.", _sessionCreationRetryInterval.TotalSeconds);
await HostContext.Delay(_sessionCreationRetryInterval, token);
}
}
}
19
View Source File : StreamString.cs
License : MIT License
Project Creator : actions
License : MIT License
Project Creator : actions
public async Task<Int32> ReadInt32Async(CancellationToken cancellationToken)
{
byte[] readBytes = new byte[sizeof(Int32)];
int dataread = 0;
while (sizeof(Int32) - dataread > 0 && (!cancellationToken.IsCancellationRequested))
{
Task<int> op = _ioStream.ReadAsync(readBytes, dataread, sizeof(Int32) - dataread, cancellationToken);
int newData = 0;
newData = await op.WithCancellation(cancellationToken);
dataread += newData;
if (0 == newData)
{
await Task.Delay(100, cancellationToken);
}
}
cancellationToken.ThrowIfCancellationRequested();
return BitConverter.ToInt32(readBytes, 0);
}
19
View Source File : StreamString.cs
License : MIT License
Project Creator : actions
License : MIT License
Project Creator : actions
public async Task WriteStringAsync(string outString, CancellationToken cancellationToken)
{
byte[] outBuffer = streamEncoding.GetBytes(outString);
Int32 len = outBuffer.Length;
if (len > MaxStringSize)
{
throw new ArgumentOutOfRangeException();
}
await WriteInt32Async(len, cancellationToken);
cancellationToken.ThrowIfCancellationRequested();
Task op = _ioStream.WriteAsync(outBuffer, 0, len, cancellationToken);
await op.WithCancellation(cancellationToken);
op = _ioStream.FlushAsync(cancellationToken);
await op.WithCancellation(cancellationToken);
}
19
View Source File : FileContainerServer.cs
License : MIT License
Project Creator : actions
License : MIT License
Project Creator : actions
private async Task<DownloadResult> DownloadAsync(RunnerActionPluginExecutionContext context, int downloaderId, CancellationToken token)
{
List<DownloadInfo> failedFiles = new List<DownloadInfo>();
Stopwatch downloadTimer = new Stopwatch();
while (_fileDownloadQueue.TryDequeue(out DownloadInfo fileToDownload))
{
token.ThrowIfCancellationRequested();
try
{
int retryCount = 0;
bool downloadFailed = false;
while (true)
{
try
{
context.Debug($"Start downloading file: '{fileToDownload.ItemPath}' (Downloader {downloaderId})");
downloadTimer.Restart();
using (FileStream fs = new FileStream(fileToDownload.LocalPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: _defaultFileStreamBufferSize, useAsync: true))
using (var downloadStream = await _fileContainerHttpClient.DownloadFileAsync(_containerId, fileToDownload.ItemPath, token, _projectId))
{
await downloadStream.CopyToAsync(fs, _defaultCopyBufferSize, token);
await fs.FlushAsync(token);
downloadTimer.Stop();
context.Debug($"File: '{fileToDownload.LocalPath}' took {downloadTimer.ElapsedMilliseconds} milliseconds to finish download (Downloader {downloaderId})");
break;
}
}
catch (OperationCanceledException) when (token.IsCancellationRequested)
{
context.Debug($"Download has been cancelled while downloading {fileToDownload.ItemPath}. (Downloader {downloaderId})");
throw;
}
catch (Exception ex)
{
retryCount++;
context.Warning($"Fail to download '{fileToDownload.ItemPath}', error: {ex.Message} (Downloader {downloaderId})");
context.Debug(ex.ToString());
}
if (retryCount < 3)
{
var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30));
context.Warning($"Back off {backOff.TotalSeconds} seconds before retry. (Downloader {downloaderId})");
await Task.Delay(backOff);
}
else
{
// upload still failed after 3 tries.
downloadFailed = true;
break;
}
}
if (downloadFailed)
{
// tracking file that failed to download.
failedFiles.Add(fileToDownload);
}
Interlocked.Increment(ref _downloadFilesProcessed);
}
catch (Exception ex)
{
// We should never
context.Error($"Error '{ex.Message}' when downloading file '{fileToDownload}'. (Downloader {downloaderId})");
throw ex;
}
}
return new DownloadResult(failedFiles);
}
19
View Source File : FileContainerServer.cs
License : MIT License
Project Creator : actions
License : MIT License
Project Creator : actions
private async Task<UploadResult> UploadAsync(RunnerActionPluginExecutionContext context, int uploaderId, CancellationToken token)
{
List<string> failedFiles = new List<string>();
long uploadedSize = 0;
string fileToUpload;
Stopwatch uploadTimer = new Stopwatch();
while (_fileUploadQueue.TryDequeue(out fileToUpload))
{
token.ThrowIfCancellationRequested();
try
{
using (FileStream fs = File.Open(fileToUpload, FileMode.Open, FileAccess.Read, FileShare.Read))
{
string itemPath = (_containerPath.TrimEnd('/') + "/" + fileToUpload.Remove(0, _sourceParentDirectory.Length + 1)).Replace('\\', '/');
bool failAndExit = false;
try
{
uploadTimer.Restart();
using (HttpResponseMessage response = await _fileContainerHttpClient.UploadFileAsync(_containerId, itemPath, fs, _projectId, cancellationToken: token, chunkSize: 4 * 1024 * 1024))
{
if (response == null || response.StatusCode != HttpStatusCode.Created)
{
context.Output($"Unable to copy file to server StatusCode={response?.StatusCode}: {response?.ReasonPhrase}. Source file path: {fileToUpload}. Target server path: {itemPath}");
if (response?.StatusCode == HttpStatusCode.Conflict)
{
// fail upload task but continue with any other files
context.Error($"Error '{fileToUpload}' has already been uploaded.");
}
else if (_fileContainerHttpClient.IsFastFailResponse(response))
{
// Fast fail: we received an http status code where we should abandon our efforts
context.Output($"Cannot continue uploading files, so draining upload queue of {_fileUploadQueue.Count} items.");
DrainUploadQueue(context);
failedFiles.Clear();
failAndExit = true;
throw new UploadFailedException($"Critical failure uploading '{fileToUpload}'");
}
else
{
context.Debug($"Adding '{fileToUpload}' to retry list.");
failedFiles.Add(fileToUpload);
}
throw new UploadFailedException($"Http failure response '{response?.StatusCode}': '{response?.ReasonPhrase}' while uploading '{fileToUpload}'");
}
uploadTimer.Stop();
context.Debug($"File: '{fileToUpload}' took {uploadTimer.ElapsedMilliseconds} milliseconds to finish upload");
uploadedSize += fs.Length;
OutputLogForFile(context, fileToUpload, $"Detail upload trace for file: {itemPath}", context.Debug);
}
}
catch (OperationCanceledException) when (token.IsCancellationRequested)
{
context.Output($"File upload has been cancelled during upload file: '{fileToUpload}'.");
throw;
}
catch (Exception ex)
{
context.Output($"Fail to upload '{fileToUpload}' due to '{ex.Message}'.");
context.Output(ex.ToString());
OutputLogForFile(context, fileToUpload, $"Detail upload trace for file that fail to upload: {itemPath}", context.Output);
if (failAndExit)
{
context.Debug("Exiting upload.");
throw;
}
}
}
Interlocked.Increment(ref _uploadFilesProcessed);
}
catch (Exception ex)
{
context.Output($"File error '{ex.Message}' when uploading file '{fileToUpload}'.");
throw ex;
}
}
return new UploadResult(failedFiles, uploadedSize);
}
19
View Source File : MessageListener.cs
License : MIT License
Project Creator : actions
License : MIT License
Project Creator : actions
public async Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token)
{
Trace.Entering();
ArgUtil.NotNull(_session, nameof(_session));
ArgUtil.NotNull(_settings, nameof(_settings));
bool encounteringError = false;
int continuousError = 0;
string errorMessage = string.Empty;
Stopwatch heartbeat = new Stopwatch();
heartbeat.Restart();
while (true)
{
token.ThrowIfCancellationRequested();
TaskAgentMessage message = null;
try
{
message = await _runnerServer.GetAgentMessageAsync(_settings.PoolId,
_session.SessionId,
_lastMessageId,
token);
// Decrypt the message body if the session is using encryption
message = DecryptMessage(message);
if (message != null)
{
_lastMessageId = message.MessageId;
}
if (encounteringError) //print the message once only if there was an error
{
_term.WriteLine($"{DateTime.UtcNow:u}: Runner reconnected.");
encounteringError = false;
continuousError = 0;
}
}
catch (OperationCanceledException) when (token.IsCancellationRequested)
{
Trace.Info("Get next message has been cancelled.");
throw;
}
catch (TaskAgentAccessTokenExpiredException)
{
Trace.Info("Runner OAuth token has been revoked. Unable to pull message.");
throw;
}
catch (Exception ex)
{
Trace.Error("Catch exception during get next message.");
Trace.Error(ex);
// don't retry if SkipSessionRecover = true, DT service will delete agent session to stop agent from taking more jobs.
if (ex is TaskAgentSessionExpiredException && !_settings.SkipSessionRecover && await CreateSessionAsync(token))
{
Trace.Info($"{nameof(TaskAgentSessionExpiredException)} received, recovered by recreate session.");
}
else if (!IsGetNextMessageExceptionRetriable(ex))
{
throw;
}
else
{
continuousError++;
//retry after a random backoff to avoid service throttling
//in case of there is a service error happened and all agents get kicked off of the long poll and all agent try to reconnect back at the same time.
if (continuousError <= 5)
{
// random backoff [15, 30]
_getNextMessageRetryInterval = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), _getNextMessageRetryInterval);
}
else
{
// more aggressive backoff [30, 60]
_getNextMessageRetryInterval = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(60), _getNextMessageRetryInterval);
}
if (!encounteringError)
{
//print error only on the first consecutive error
_term.WriteError($"{DateTime.UtcNow:u}: Runner connect error: {ex.Message}. Retrying until reconnected.");
encounteringError = true;
}
// re-create VssConnection before next retry
await _runnerServer.RefreshConnectionAsync(RunnerConnectionType.MessageQueue, TimeSpan.FromSeconds(60));
Trace.Info("Sleeping for {0} seconds before retrying.", _getNextMessageRetryInterval.TotalSeconds);
await HostContext.Delay(_getNextMessageRetryInterval, token);
}
}
if (message == null)
{
if (heartbeat.Elapsed > TimeSpan.FromMinutes(30))
{
Trace.Info($"No message retrieved from session '{_session.SessionId}' within last 30 minutes.");
heartbeat.Restart();
}
else
{
Trace.Verbose($"No message retrieved from session '{_session.SessionId}'.");
}
continue;
}
Trace.Info($"Message '{message.MessageId}' received from session '{_session.SessionId}'.");
return message;
}
}
19
View Source File : GitSourceProvider.cs
License : MIT License
Project Creator : actions
License : MIT License
Project Creator : actions
public async Task GetSourceAsync(
RunnerActionPluginExecutionContext executionContext,
string repositoryPath,
string repoFullName,
string sourceBranch,
string sourceVersion,
bool clean,
string submoduleInput,
int fetchDepth,
bool gitLfsSupport,
string accessToken,
CancellationToken cancellationToken)
{
// Validate args.
ArgUtil.NotNull(executionContext, nameof(executionContext));
Dictionary<string, string> configModifications = new Dictionary<string, string>();
executionContext.Output($"Syncing repository: {repoFullName}");
Uri repositoryUrl = new Uri($"https://github.com/{repoFullName}");
if (!repositoryUrl.IsAbsoluteUri)
{
throw new InvalidOperationException("Repository url need to be an absolute uri.");
}
string targetPath = repositoryPath;
// input Submodules can be ['', true, false, recursive]
// '' or false indicate don't checkout submodules
// true indicate checkout top level submodules
// recursive indicate checkout submodules recursively
bool checkoutSubmodules = false;
bool checkoutNestedSubmodules = false;
if (!string.IsNullOrEmpty(submoduleInput))
{
if (string.Equals(submoduleInput, Pipelines.PipelineConstants.CheckoutTaskInputs.SubmodulesOptions.Recursive, StringComparison.OrdinalIgnoreCase))
{
checkoutSubmodules = true;
checkoutNestedSubmodules = true;
}
else
{
checkoutSubmodules = StringUtil.ConvertToBoolean(submoduleInput);
}
}
executionContext.Debug($"repository url={repositoryUrl}");
executionContext.Debug($"targetPath={targetPath}");
executionContext.Debug($"sourceBranch={sourceBranch}");
executionContext.Debug($"sourceVersion={sourceVersion}");
executionContext.Debug($"clean={clean}");
executionContext.Debug($"checkoutSubmodules={checkoutSubmodules}");
executionContext.Debug($"checkoutNestedSubmodules={checkoutNestedSubmodules}");
executionContext.Debug($"fetchDepth={fetchDepth}");
executionContext.Debug($"gitLfsSupport={gitLfsSupport}");
// Initialize git command manager with additional environment variables.
Dictionary<string, string> gitEnv = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
// Disable git prompt
gitEnv["GIT_TERMINAL_PROMPT"] = "0";
// Disable prompting for git credential manager
gitEnv["GCM_INTERACTIVE"] = "Never";
// Git-lfs will try to pull down replacedet if any of the local/user/system setting exist.
// If customer didn't enable `LFS` in their pipeline definition, we will use ENV to disable LFS fetch/checkout.
if (!gitLfsSupport)
{
gitEnv["GIT_LFS_SKIP_SMUDGE"] = "1";
}
// Add the public variables.
foreach (var variable in executionContext.Variables)
{
// Add the variable using the formatted name.
string formattedKey = (variable.Key ?? string.Empty).Replace('.', '_').Replace(' ', '_').ToUpperInvariant();
gitEnv[formattedKey] = variable.Value?.Value ?? string.Empty;
}
GitCliManager gitCommandManager = new GitCliManager(gitEnv);
await gitCommandManager.LoadGitExecutionInfo(executionContext);
// Make sure the build machine met all requirements for the git repository
// For now, the requirement we have are:
// 1. git version greater than 2.9 since we need to use auth header.
// 2. git-lfs version greater than 2.1 since we need to use auth header.
// 3. git version greater than 2.14.2 if use SChannel for SSL backend (Windows only)
RequirementCheck(executionContext, gitCommandManager, gitLfsSupport);
// prepare askpreplaced for client cert private key, if the repository's endpoint url match the runner config url
var systemConnection = executionContext.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
// Check the current contents of the root folder to see if there is already a repo
// If there is a repo, see if it matches the one we are expecting to be there based on the remote fetch url
// if the repo is not what we expect, remove the folder
if (!await IsRepositoryOriginUrlMatch(executionContext, gitCommandManager, targetPath, repositoryUrl))
{
// Delete source folder
IOUtil.DeleteDirectory(targetPath, cancellationToken);
}
else
{
// delete the index.lock file left by previous canceled build or any operation cause git.exe crash last time.
string lockFile = Path.Combine(targetPath, ".git\\index.lock");
if (File.Exists(lockFile))
{
try
{
File.Delete(lockFile);
}
catch (Exception ex)
{
executionContext.Debug($"Unable to delete the index.lock file: {lockFile}");
executionContext.Debug(ex.ToString());
}
}
// delete the shallow.lock file left by previous canceled build or any operation cause git.exe crash last time.
string shallowLockFile = Path.Combine(targetPath, ".git\\shallow.lock");
if (File.Exists(shallowLockFile))
{
try
{
File.Delete(shallowLockFile);
}
catch (Exception ex)
{
executionContext.Debug($"Unable to delete the shallow.lock file: {shallowLockFile}");
executionContext.Debug(ex.ToString());
}
}
// When repo.clean is selected for a git repo, execute git clean -ffdx and git reset --hard HEAD on the current repo.
// This will help us save the time to reclone the entire repo.
// If any git commands exit with non-zero return code or any exception happened during git.exe invoke, fall back to delete the repo folder.
if (clean)
{
Boolean softCleanSucceed = true;
// git clean -ffdx
int exitCode_clean = await gitCommandManager.GitClean(executionContext, targetPath);
if (exitCode_clean != 0)
{
executionContext.Debug($"'git clean -ffdx' failed with exit code {exitCode_clean}, this normally caused by:\n 1) Path too long\n 2) Permission issue\n 3) File in use\nFor futher investigation, manually run 'git clean -ffdx' on repo root: {targetPath} after each build.");
softCleanSucceed = false;
}
// git reset --hard HEAD
if (softCleanSucceed)
{
int exitCode_reset = await gitCommandManager.GitReset(executionContext, targetPath);
if (exitCode_reset != 0)
{
executionContext.Debug($"'git reset --hard HEAD' failed with exit code {exitCode_reset}\nFor futher investigation, manually run 'git reset --hard HEAD' on repo root: {targetPath} after each build.");
softCleanSucceed = false;
}
}
// git clean -ffdx and git reset --hard HEAD for each submodule
if (checkoutSubmodules)
{
if (softCleanSucceed)
{
int exitCode_submoduleclean = await gitCommandManager.GitSubmoduleClean(executionContext, targetPath);
if (exitCode_submoduleclean != 0)
{
executionContext.Debug($"'git submodule foreach git clean -ffdx' failed with exit code {exitCode_submoduleclean}\nFor futher investigation, manually run 'git submodule foreach git clean -ffdx' on repo root: {targetPath} after each build.");
softCleanSucceed = false;
}
}
if (softCleanSucceed)
{
int exitCode_submodulereset = await gitCommandManager.GitSubmoduleReset(executionContext, targetPath);
if (exitCode_submodulereset != 0)
{
executionContext.Debug($"'git submodule foreach git reset --hard HEAD' failed with exit code {exitCode_submodulereset}\nFor futher investigation, manually run 'git submodule foreach git reset --hard HEAD' on repo root: {targetPath} after each build.");
softCleanSucceed = false;
}
}
}
if (!softCleanSucceed)
{
//fall back
executionContext.Warning("Unable to run \"git clean -ffdx\" and \"git reset --hard HEAD\" successfully, delete source folder instead.");
IOUtil.DeleteDirectory(targetPath, cancellationToken);
}
}
}
// if the folder is missing, create it
if (!Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
}
// if the folder contains a .git folder, it means the folder contains a git repo that matches the remote url and in a clean state.
// we will run git fetch to update the repo.
if (!Directory.Exists(Path.Combine(targetPath, ".git")))
{
// init git repository
int exitCode_init = await gitCommandManager.GitInit(executionContext, targetPath);
if (exitCode_init != 0)
{
throw new InvalidOperationException($"Unable to use git.exe init repository under {targetPath}, 'git init' failed with exit code: {exitCode_init}");
}
int exitCode_addremote = await gitCommandManager.GitRemoteAdd(executionContext, targetPath, "origin", repositoryUrl.AbsoluteUri);
if (exitCode_addremote != 0)
{
throw new InvalidOperationException($"Unable to use git.exe add remote 'origin', 'git remote add' failed with exit code: {exitCode_addremote}");
}
}
cancellationToken.ThrowIfCancellationRequested();
// disable git auto gc
int exitCode_disableGC = await gitCommandManager.GitDisableAutoGC(executionContext, targetPath);
if (exitCode_disableGC != 0)
{
executionContext.Warning("Unable turn off git auto garbage collection, git fetch operation may trigger auto garbage collection which will affect the performance of fetching.");
}
// always remove any possible left extraheader setting from git config.
if (await gitCommandManager.GitConfigExist(executionContext, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader"))
{
executionContext.Debug("Remove any extraheader setting from git config.");
await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader", string.Empty);
}
List<string> additionalFetchArgs = new List<string>();
List<string> additionalLfsFetchArgs = new List<string>();
// Add http.https://github.com.extraheader=... to gitconfig
// accessToken as basic auth header to handle any auth challenge from github.com
string configKey = $"http.https://github.com/.extraheader";
string configValue = $"\"AUTHORIZATION: {GenerateBasicAuthHeader(executionContext, accessToken)}\"";
configModifications[configKey] = configValue.Trim('\"');
int exitCode_config = await gitCommandManager.GitConfig(executionContext, targetPath, configKey, configValue);
if (exitCode_config != 0)
{
throw new InvalidOperationException($"Git config failed with exit code: {exitCode_config}");
}
// Prepare gitlfs url for fetch and checkout
if (gitLfsSupport)
{
// Initialize git lfs by execute 'git lfs install'
executionContext.Debug("Setup the local Git hooks for Git LFS.");
int exitCode_lfsInstall = await gitCommandManager.GitLFSInstall(executionContext, targetPath);
if (exitCode_lfsInstall != 0)
{
throw new InvalidOperationException($"Git-lfs installation failed with exit code: {exitCode_lfsInstall}");
}
}
List<string> additionalFetchSpecs = new List<string>();
additionalFetchSpecs.Add("+refs/heads/*:refs/remotes/origin/*");
if (IsPullRequest(sourceBranch))
{
additionalFetchSpecs.Add($"+{sourceBranch}:{GetRemoteRefName(sourceBranch)}");
}
int exitCode_fetch = await gitCommandManager.GitFetch(executionContext, targetPath, "origin", fetchDepth, additionalFetchSpecs, string.Join(" ", additionalFetchArgs), cancellationToken);
if (exitCode_fetch != 0)
{
throw new InvalidOperationException($"Git fetch failed with exit code: {exitCode_fetch}");
}
// Checkout
// sourceToBuild is used for checkout
// if sourceBranch is a PR branch or sourceVersion is null, make sure branch name is a remote branch. we need checkout to detached head.
// (change refs/heads to refs/remotes/origin, refs/pull to refs/remotes/pull, or leave it as it when the branch name doesn't contain refs/...)
// if sourceVersion provide, just use that for checkout, since when you checkout a commit, it will end up in detached head.
cancellationToken.ThrowIfCancellationRequested();
string sourcesToBuild;
if (IsPullRequest(sourceBranch) || string.IsNullOrEmpty(sourceVersion))
{
sourcesToBuild = GetRemoteRefName(sourceBranch);
}
else
{
sourcesToBuild = sourceVersion;
}
// fetch lfs object upfront, this will avoid fetch lfs object during checkout which cause checkout taking forever
// since checkout will fetch lfs object 1 at a time, while git lfs fetch will fetch lfs object in parallel.
if (gitLfsSupport)
{
int exitCode_lfsFetch = await gitCommandManager.GitLFSFetch(executionContext, targetPath, "origin", sourcesToBuild, string.Join(" ", additionalLfsFetchArgs), cancellationToken);
if (exitCode_lfsFetch != 0)
{
// local repository is shallow repository, lfs fetch may fail due to lack of commits history.
// this will happen when the checkout commit is older than tip -> fetchDepth
if (fetchDepth > 0)
{
executionContext.Warning($"Git lfs fetch failed on shallow repository, this might because of git fetch with depth '{fetchDepth}' doesn't include the lfs fetch commit '{sourcesToBuild}'.");
}
// git lfs fetch failed, get lfs log, the log is critical for debug.
int exitCode_lfsLogs = await gitCommandManager.GitLFSLogs(executionContext, targetPath);
throw new InvalidOperationException($"Git lfs fetch failed with exit code: {exitCode_lfsFetch}. Git lfs logs returned with exit code: {exitCode_lfsLogs}.");
}
}
// Finally, checkout the sourcesToBuild (if we didn't find a valid git object this will throw)
int exitCode_checkout = await gitCommandManager.GitCheckout(executionContext, targetPath, sourcesToBuild, cancellationToken);
if (exitCode_checkout != 0)
{
// local repository is shallow repository, checkout may fail due to lack of commits history.
// this will happen when the checkout commit is older than tip -> fetchDepth
if (fetchDepth > 0)
{
executionContext.Warning($"Git checkout failed on shallow repository, this might because of git fetch with depth '{fetchDepth}' doesn't include the checkout commit '{sourcesToBuild}'.");
}
throw new InvalidOperationException($"Git checkout failed with exit code: {exitCode_checkout}");
}
// Submodule update
if (checkoutSubmodules)
{
cancellationToken.ThrowIfCancellationRequested();
int exitCode_submoduleSync = await gitCommandManager.GitSubmoduleSync(executionContext, targetPath, checkoutNestedSubmodules, cancellationToken);
if (exitCode_submoduleSync != 0)
{
throw new InvalidOperationException($"Git submodule sync failed with exit code: {exitCode_submoduleSync}");
}
List<string> additionalSubmoduleUpdateArgs = new List<string>();
int exitCode_submoduleUpdate = await gitCommandManager.GitSubmoduleUpdate(executionContext, targetPath, fetchDepth, string.Join(" ", additionalSubmoduleUpdateArgs), checkoutNestedSubmodules, cancellationToken);
if (exitCode_submoduleUpdate != 0)
{
throw new InvalidOperationException($"Git submodule update failed with exit code: {exitCode_submoduleUpdate}");
}
}
// Set intra-task variable for post job cleanup
executionContext.SetIntraActionState("repositoryPath", targetPath);
executionContext.SetIntraActionState("modifiedgitconfig", JsonUtility.ToString(configModifications.Keys));
foreach (var config in configModifications)
{
executionContext.SetIntraActionState(config.Key, config.Value);
}
}
19
View Source File : IOUtil.cs
License : MIT License
Project Creator : actions
License : MIT License
Project Creator : actions
public static void CopyDirectory(string source, string target, CancellationToken cancellationToken)
{
// Validate args.
ArgUtil.Directory(source, nameof(source));
ArgUtil.NotNullOrEmpty(target, nameof(target));
ArgUtil.NotNull(cancellationToken, nameof(cancellationToken));
cancellationToken.ThrowIfCancellationRequested();
// Create the target directory.
Directory.CreateDirectory(target);
// Get the file contents of the directory to copy.
DirectoryInfo sourceDir = new DirectoryInfo(source);
foreach (FileInfo sourceFile in sourceDir.GetFiles() ?? new FileInfo[0])
{
// Check if the file already exists.
cancellationToken.ThrowIfCancellationRequested();
FileInfo targetFile = new FileInfo(Path.Combine(target, sourceFile.Name));
if (!targetFile.Exists ||
sourceFile.Length != targetFile.Length ||
sourceFile.LastWriteTime != targetFile.LastWriteTime)
{
// Copy the file.
sourceFile.CopyTo(targetFile.FullName, true);
}
}
// Copy the subdirectories.
foreach (DirectoryInfo subDir in sourceDir.GetDirectories() ?? new DirectoryInfo[0])
{
CopyDirectory(
source: subDir.FullName,
target: Path.Combine(target, subDir.Name),
cancellationToken: cancellationToken);
}
}
19
View Source File : ProcessInvoker.cs
License : MIT License
Project Creator : actions
License : MIT License
Project Creator : actions
public async Task<int> ExecuteAsync(
string workingDirectory,
string fileName,
string arguments,
IDictionary<string, string> environment,
bool requireExitCodeZero,
Encoding outputEncoding,
bool killProcessOnCancel,
Channel<string> redirectStandardIn,
bool inheritConsoleHandler,
bool keepStandardInOpen,
bool highPriorityProcess,
CancellationToken cancellationToken)
{
ArgUtil.Null(_proc, nameof(_proc));
ArgUtil.NotNullOrEmpty(fileName, nameof(fileName));
Trace.Info("Starting process:");
Trace.Info($" File name: '{fileName}'");
Trace.Info($" Arguments: '{arguments}'");
Trace.Info($" Working directory: '{workingDirectory}'");
Trace.Info($" Require exit code zero: '{requireExitCodeZero}'");
Trace.Info($" Encoding web name: {outputEncoding?.WebName} ; code page: '{outputEncoding?.CodePage}'");
Trace.Info($" Force kill process on cancellation: '{killProcessOnCancel}'");
Trace.Info($" Redirected STDIN: '{redirectStandardIn != null}'");
Trace.Info($" Persist current code page: '{inheritConsoleHandler}'");
Trace.Info($" Keep redirected STDIN open: '{keepStandardInOpen}'");
Trace.Info($" High priority process: '{highPriorityProcess}'");
_proc = new Process();
_proc.StartInfo.FileName = fileName;
_proc.StartInfo.Arguments = arguments;
_proc.StartInfo.WorkingDirectory = workingDirectory;
_proc.StartInfo.UseShellExecute = false;
_proc.StartInfo.CreateNoWindow = !inheritConsoleHandler;
_proc.StartInfo.RedirectStandardInput = true;
_proc.StartInfo.RedirectStandardError = true;
_proc.StartInfo.RedirectStandardOutput = true;
// Ensure we process STDERR even the process exit event happen before we start read STDERR stream.
if (_proc.StartInfo.RedirectStandardError)
{
Interlocked.Increment(ref _asyncStreamReaderCount);
}
// Ensure we process STDOUT even the process exit event happen before we start read STDOUT stream.
if (_proc.StartInfo.RedirectStandardOutput)
{
Interlocked.Increment(ref _asyncStreamReaderCount);
}
#if OS_WINDOWS
// If StandardErrorEncoding or StandardOutputEncoding is not specified the on the
// ProcessStartInfo object, then .NET PInvokes to resolve the default console output
// code page:
// [DllImport("api-ms-win-core-console-l1-1-0.dll", SetLastError = true)]
// public extern static uint GetConsoleOutputCP();
StringUtil.EnsureRegisterEncodings();
#endif
if (outputEncoding != null)
{
_proc.StartInfo.StandardErrorEncoding = outputEncoding;
_proc.StartInfo.StandardOutputEncoding = outputEncoding;
}
// Copy the environment variables.
if (environment != null && environment.Count > 0)
{
foreach (KeyValuePair<string, string> kvp in environment)
{
_proc.StartInfo.Environment[kvp.Key] = kvp.Value;
}
}
// Indicate GitHub Actions process.
_proc.StartInfo.Environment["GITHUB_ACTIONS"] = "true";
// Set CI=true when no one else already set it.
// CI=true is common set in most CI provider in GitHub
if (!_proc.StartInfo.Environment.ContainsKey("CI") &&
Environment.GetEnvironmentVariable("CI") == null)
{
_proc.StartInfo.Environment["CI"] = "true";
}
// Hook up the events.
_proc.EnableRaisingEvents = true;
_proc.Exited += ProcessExitedHandler;
// Start the process.
_stopWatch = Stopwatch.StartNew();
_proc.Start();
// Decrease invoked process priority, in platform specifc way, relative to parent
if (!highPriorityProcess)
{
DecreaseProcessPriority(_proc);
}
// Start the standard error notifications, if appropriate.
if (_proc.StartInfo.RedirectStandardError)
{
StartReadStream(_proc.StandardError, _errorData);
}
// Start the standard output notifications, if appropriate.
if (_proc.StartInfo.RedirectStandardOutput)
{
StartReadStream(_proc.StandardOutput, _outputData);
}
if (_proc.StartInfo.RedirectStandardInput)
{
if (redirectStandardIn != null)
{
StartWriteStream(redirectStandardIn, _proc.StandardInput, keepStandardInOpen);
}
else
{
// Close the input stream. This is done to prevent commands from blocking the build waiting for input from the user.
_proc.StandardInput.Close();
}
}
var cancellationFinished = new TaskCompletionSource<bool>();
using (var registration = cancellationToken.Register(async () =>
{
await CancelAndKillProcessTree(killProcessOnCancel);
cancellationFinished.TrySetResult(true);
}))
{
Trace.Info($"Process started with process id {_proc.Id}, waiting for process exit.");
while (true)
{
Task outputSignal = _outputProcessEvent.WaitAsync();
var signaled = await Task.WhenAny(outputSignal, _processExitedCompletionSource.Task);
if (signaled == outputSignal)
{
ProcessOutput();
}
else
{
_stopWatch.Stop();
break;
}
}
// Just in case there was some pending output when the process shut down go ahead and check the
// data buffers one last time before returning
ProcessOutput();
if (cancellationToken.IsCancellationRequested)
{
// Ensure cancellation also finish on the cancellationToken.Register thread.
await cancellationFinished.Task;
Trace.Info($"Process Cancellation finished.");
}
Trace.Info($"Finished process {_proc.Id} with exit code {_proc.ExitCode}, and elapsed time {_stopWatch.Elapsed}.");
}
cancellationToken.ThrowIfCancellationRequested();
// Wait for process to finish.
if (_proc.ExitCode != 0 && requireExitCodeZero)
{
throw new ProcessExitCodeException(exitCode: _proc.ExitCode, fileName: fileName, arguments: arguments);
}
return _proc.ExitCode;
}
19
View Source File : GitSourceProvider.cs
License : MIT License
Project Creator : actions
License : MIT License
Project Creator : actions
public async Task GetSourceAsync(
RunnerActionPluginExecutionContext executionContext,
string repositoryPath,
string repoFullName,
string sourceBranch,
string sourceVersion,
bool clean,
string submoduleInput,
int fetchDepth,
bool gitLfsSupport,
string accessToken,
CancellationToken cancellationToken)
{
// Validate args.
ArgUtil.NotNull(executionContext, nameof(executionContext));
executionContext.Output($"Syncing repository: {repoFullName}");
// Repository URL
var githubUrl = executionContext.GetGitHubContext("server_url");
var githubUri = new Uri(!string.IsNullOrEmpty(githubUrl) ? githubUrl : "https://github.com");
var portInfo = githubUri.IsDefaultPort ? string.Empty : $":{githubUri.Port}";
Uri repositoryUrl = new Uri($"{githubUri.Scheme}://{githubUri.Host}{portInfo}/{repoFullName}");
if (!repositoryUrl.IsAbsoluteUri)
{
throw new InvalidOperationException("Repository url need to be an absolute uri.");
}
string targetPath = repositoryPath;
// input Submodules can be ['', true, false, recursive]
// '' or false indicate don't checkout submodules
// true indicate checkout top level submodules
// recursive indicate checkout submodules recursively
bool checkoutSubmodules = false;
bool checkoutNestedSubmodules = false;
if (!string.IsNullOrEmpty(submoduleInput))
{
if (string.Equals(submoduleInput, Pipelines.PipelineConstants.CheckoutTaskInputs.SubmodulesOptions.Recursive, StringComparison.OrdinalIgnoreCase))
{
checkoutSubmodules = true;
checkoutNestedSubmodules = true;
}
else
{
checkoutSubmodules = StringUtil.ConvertToBoolean(submoduleInput);
}
}
executionContext.Debug($"repository url={repositoryUrl}");
executionContext.Debug($"targetPath={targetPath}");
executionContext.Debug($"sourceBranch={sourceBranch}");
executionContext.Debug($"sourceVersion={sourceVersion}");
executionContext.Debug($"clean={clean}");
executionContext.Debug($"checkoutSubmodules={checkoutSubmodules}");
executionContext.Debug($"checkoutNestedSubmodules={checkoutNestedSubmodules}");
executionContext.Debug($"fetchDepth={fetchDepth}");
executionContext.Debug($"gitLfsSupport={gitLfsSupport}");
// Initialize git command manager with additional environment variables.
Dictionary<string, string> gitEnv = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
// Disable prompting for git credential manager
gitEnv["GCM_INTERACTIVE"] = "Never";
// Git-lfs will try to pull down replacedet if any of the local/user/system setting exist.
// If customer didn't enable `LFS` in their pipeline definition, we will use ENV to disable LFS fetch/checkout.
if (!gitLfsSupport)
{
gitEnv["GIT_LFS_SKIP_SMUDGE"] = "1";
}
// Add the public variables.
foreach (var variable in executionContext.Variables)
{
// Add the variable using the formatted name.
string formattedKey = (variable.Key ?? string.Empty).Replace('.', '_').Replace(' ', '_').ToUpperInvariant();
gitEnv[formattedKey] = variable.Value?.Value ?? string.Empty;
}
GitCliManager gitCommandManager = new GitCliManager(gitEnv);
await gitCommandManager.LoadGitExecutionInfo(executionContext);
// Make sure the build machine met all requirements for the git repository
// For now, the requirement we have are:
// 1. git version greater than 2.9 since we need to use auth header.
// 2. git-lfs version greater than 2.1 since we need to use auth header.
// 3. git version greater than 2.14.2 if use SChannel for SSL backend (Windows only)
RequirementCheck(executionContext, gitCommandManager, gitLfsSupport);
// prepare askpreplaced for client cert private key, if the repository's endpoint url match the runner config url
var systemConnection = executionContext.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
// Check the current contents of the root folder to see if there is already a repo
// If there is a repo, see if it matches the one we are expecting to be there based on the remote fetch url
// if the repo is not what we expect, remove the folder
if (!await IsRepositoryOriginUrlMatch(executionContext, gitCommandManager, targetPath, repositoryUrl))
{
// Delete source folder
IOUtil.DeleteDirectory(targetPath, cancellationToken);
}
else
{
// delete the index.lock file left by previous canceled build or any operation cause git.exe crash last time.
string lockFile = Path.Combine(targetPath, ".git\\index.lock");
if (File.Exists(lockFile))
{
try
{
File.Delete(lockFile);
}
catch (Exception ex)
{
executionContext.Debug($"Unable to delete the index.lock file: {lockFile}");
executionContext.Debug(ex.ToString());
}
}
// delete the shallow.lock file left by previous canceled build or any operation cause git.exe crash last time.
string shallowLockFile = Path.Combine(targetPath, ".git\\shallow.lock");
if (File.Exists(shallowLockFile))
{
try
{
File.Delete(shallowLockFile);
}
catch (Exception ex)
{
executionContext.Debug($"Unable to delete the shallow.lock file: {shallowLockFile}");
executionContext.Debug(ex.ToString());
}
}
// When repo.clean is selected for a git repo, execute git clean -ffdx and git reset --hard HEAD on the current repo.
// This will help us save the time to reclone the entire repo.
// If any git commands exit with non-zero return code or any exception happened during git.exe invoke, fall back to delete the repo folder.
if (clean)
{
Boolean softCleanSucceed = true;
// git clean -ffdx
int exitCode_clean = await gitCommandManager.GitClean(executionContext, targetPath);
if (exitCode_clean != 0)
{
executionContext.Debug($"'git clean -ffdx' failed with exit code {exitCode_clean}, this normally caused by:\n 1) Path too long\n 2) Permission issue\n 3) File in use\nFor futher investigation, manually run 'git clean -ffdx' on repo root: {targetPath} after each build.");
softCleanSucceed = false;
}
// git reset --hard HEAD
if (softCleanSucceed)
{
int exitCode_reset = await gitCommandManager.GitReset(executionContext, targetPath);
if (exitCode_reset != 0)
{
executionContext.Debug($"'git reset --hard HEAD' failed with exit code {exitCode_reset}\nFor futher investigation, manually run 'git reset --hard HEAD' on repo root: {targetPath} after each build.");
softCleanSucceed = false;
}
}
// git clean -ffdx and git reset --hard HEAD for each submodule
if (checkoutSubmodules)
{
if (softCleanSucceed)
{
int exitCode_submoduleclean = await gitCommandManager.GitSubmoduleClean(executionContext, targetPath);
if (exitCode_submoduleclean != 0)
{
executionContext.Debug($"'git submodule foreach git clean -ffdx' failed with exit code {exitCode_submoduleclean}\nFor futher investigation, manually run 'git submodule foreach git clean -ffdx' on repo root: {targetPath} after each build.");
softCleanSucceed = false;
}
}
if (softCleanSucceed)
{
int exitCode_submodulereset = await gitCommandManager.GitSubmoduleReset(executionContext, targetPath);
if (exitCode_submodulereset != 0)
{
executionContext.Debug($"'git submodule foreach git reset --hard HEAD' failed with exit code {exitCode_submodulereset}\nFor futher investigation, manually run 'git submodule foreach git reset --hard HEAD' on repo root: {targetPath} after each build.");
softCleanSucceed = false;
}
}
}
if (!softCleanSucceed)
{
//fall back
executionContext.Warning("Unable to run \"git clean -ffdx\" and \"git reset --hard HEAD\" successfully, delete source folder instead.");
IOUtil.DeleteDirectory(targetPath, cancellationToken);
}
}
}
// if the folder is missing, create it
if (!Directory.Exists(targetPath))
{
Directory.CreateDirectory(targetPath);
}
// if the folder contains a .git folder, it means the folder contains a git repo that matches the remote url and in a clean state.
// we will run git fetch to update the repo.
if (!Directory.Exists(Path.Combine(targetPath, ".git")))
{
// init git repository
int exitCode_init = await gitCommandManager.GitInit(executionContext, targetPath);
if (exitCode_init != 0)
{
throw new InvalidOperationException($"Unable to use git.exe init repository under {targetPath}, 'git init' failed with exit code: {exitCode_init}");
}
int exitCode_addremote = await gitCommandManager.GitRemoteAdd(executionContext, targetPath, "origin", repositoryUrl.AbsoluteUri);
if (exitCode_addremote != 0)
{
throw new InvalidOperationException($"Unable to use git.exe add remote 'origin', 'git remote add' failed with exit code: {exitCode_addremote}");
}
}
cancellationToken.ThrowIfCancellationRequested();
// disable git auto gc
int exitCode_disableGC = await gitCommandManager.GitDisableAutoGC(executionContext, targetPath);
if (exitCode_disableGC != 0)
{
executionContext.Warning("Unable turn off git auto garbage collection, git fetch operation may trigger auto garbage collection which will affect the performance of fetching.");
}
// always remove any possible left extraheader setting from git config.
if (await gitCommandManager.GitConfigExist(executionContext, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader"))
{
executionContext.Debug("Remove any extraheader setting from git config.");
await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader", string.Empty);
}
List<string> additionalFetchArgs = new List<string>();
List<string> additionalLfsFetchArgs = new List<string>();
// add accessToken as basic auth header to handle auth challenge.
if (!string.IsNullOrEmpty(accessToken))
{
additionalFetchArgs.Add($"-c http.extraheader=\"AUTHORIZATION: {GenerateBasicAuthHeader(executionContext, accessToken)}\"");
}
// Prepare gitlfs url for fetch and checkout
if (gitLfsSupport)
{
// Initialize git lfs by execute 'git lfs install'
executionContext.Debug("Setup the local Git hooks for Git LFS.");
int exitCode_lfsInstall = await gitCommandManager.GitLFSInstall(executionContext, targetPath);
if (exitCode_lfsInstall != 0)
{
throw new InvalidOperationException($"Git-lfs installation failed with exit code: {exitCode_lfsInstall}");
}
if (!string.IsNullOrEmpty(accessToken))
{
string authorityUrl = repositoryUrl.AbsoluteUri.Replace(repositoryUrl.PathAndQuery, string.Empty);
additionalLfsFetchArgs.Add($"-c http.{authorityUrl}.extraheader=\"AUTHORIZATION: {GenerateBasicAuthHeader(executionContext, accessToken)}\"");
}
}
List<string> additionalFetchSpecs = new List<string>();
additionalFetchSpecs.Add("+refs/heads/*:refs/remotes/origin/*");
if (IsPullRequest(sourceBranch))
{
additionalFetchSpecs.Add($"+{sourceBranch}:{GetRemoteRefName(sourceBranch)}");
}
int exitCode_fetch = await gitCommandManager.GitFetch(executionContext, targetPath, "origin", fetchDepth, additionalFetchSpecs, string.Join(" ", additionalFetchArgs), cancellationToken);
if (exitCode_fetch != 0)
{
throw new InvalidOperationException($"Git fetch failed with exit code: {exitCode_fetch}");
}
// Checkout
// sourceToBuild is used for checkout
// if sourceBranch is a PR branch or sourceVersion is null, make sure branch name is a remote branch. we need checkout to detached head.
// (change refs/heads to refs/remotes/origin, refs/pull to refs/remotes/pull, or leave it as it when the branch name doesn't contain refs/...)
// if sourceVersion provide, just use that for checkout, since when you checkout a commit, it will end up in detached head.
cancellationToken.ThrowIfCancellationRequested();
string sourcesToBuild;
if (IsPullRequest(sourceBranch) || string.IsNullOrEmpty(sourceVersion))
{
sourcesToBuild = GetRemoteRefName(sourceBranch);
}
else
{
sourcesToBuild = sourceVersion;
}
// fetch lfs object upfront, this will avoid fetch lfs object during checkout which cause checkout taking forever
// since checkout will fetch lfs object 1 at a time, while git lfs fetch will fetch lfs object in parallel.
if (gitLfsSupport)
{
int exitCode_lfsFetch = await gitCommandManager.GitLFSFetch(executionContext, targetPath, "origin", sourcesToBuild, string.Join(" ", additionalLfsFetchArgs), cancellationToken);
if (exitCode_lfsFetch != 0)
{
// local repository is shallow repository, lfs fetch may fail due to lack of commits history.
// this will happen when the checkout commit is older than tip -> fetchDepth
if (fetchDepth > 0)
{
executionContext.Warning($"Git lfs fetch failed on shallow repository, this might because of git fetch with depth '{fetchDepth}' doesn't include the lfs fetch commit '{sourcesToBuild}'.");
}
// git lfs fetch failed, get lfs log, the log is critical for debug.
int exitCode_lfsLogs = await gitCommandManager.GitLFSLogs(executionContext, targetPath);
throw new InvalidOperationException($"Git lfs fetch failed with exit code: {exitCode_lfsFetch}. Git lfs logs returned with exit code: {exitCode_lfsLogs}.");
}
}
// Finally, checkout the sourcesToBuild (if we didn't find a valid git object this will throw)
int exitCode_checkout = await gitCommandManager.GitCheckout(executionContext, targetPath, sourcesToBuild, cancellationToken);
if (exitCode_checkout != 0)
{
// local repository is shallow repository, checkout may fail due to lack of commits history.
// this will happen when the checkout commit is older than tip -> fetchDepth
if (fetchDepth > 0)
{
executionContext.Warning($"Git checkout failed on shallow repository, this might because of git fetch with depth '{fetchDepth}' doesn't include the checkout commit '{sourcesToBuild}'.");
}
throw new InvalidOperationException($"Git checkout failed with exit code: {exitCode_checkout}");
}
// Submodule update
if (checkoutSubmodules)
{
cancellationToken.ThrowIfCancellationRequested();
int exitCode_submoduleSync = await gitCommandManager.GitSubmoduleSync(executionContext, targetPath, checkoutNestedSubmodules, cancellationToken);
if (exitCode_submoduleSync != 0)
{
throw new InvalidOperationException($"Git submodule sync failed with exit code: {exitCode_submoduleSync}");
}
List<string> additionalSubmoduleUpdateArgs = new List<string>();
if (!string.IsNullOrEmpty(accessToken))
{
string authorityUrl = repositoryUrl.AbsoluteUri.Replace(repositoryUrl.PathAndQuery, string.Empty);
additionalSubmoduleUpdateArgs.Add($"-c http.{authorityUrl}.extraheader=\"AUTHORIZATION: {GenerateBasicAuthHeader(executionContext, accessToken)}\"");
}
int exitCode_submoduleUpdate = await gitCommandManager.GitSubmoduleUpdate(executionContext, targetPath, fetchDepth, string.Join(" ", additionalSubmoduleUpdateArgs), checkoutNestedSubmodules, cancellationToken);
if (exitCode_submoduleUpdate != 0)
{
throw new InvalidOperationException($"Git submodule update failed with exit code: {exitCode_submoduleUpdate}");
}
}
}
19
View Source File : IOUtil.cs
License : MIT License
Project Creator : actions
License : MIT License
Project Creator : actions
public static void DeleteDirectory(string path, bool contentsOnly, bool continueOnContentDeleteError, CancellationToken cancellationToken)
{
ArgUtil.NotNullOrEmpty(path, nameof(path));
DirectoryInfo directory = new DirectoryInfo(path);
if (!directory.Exists)
{
return;
}
if (!contentsOnly)
{
// Remove the readonly flag.
RemoveReadOnly(directory);
// Check if the directory is a reparse point.
if (directory.Attributes.HasFlag(FileAttributes.ReparsePoint))
{
// Delete the reparse point directory and short-circuit.
directory.Delete();
return;
}
}
// Initialize a concurrent stack to store the directories. The directories
// cannot be deleted until the files are deleted.
var directories = new ConcurrentStack<DirectoryInfo>();
if (!contentsOnly)
{
directories.Push(directory);
}
// Create a new token source for the parallel query. The parallel query should be
// canceled after the first error is encountered. Otherwise the number of exceptions
// could get out of control for a large directory with access denied on every file.
using (var tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
{
try
{
// Recursively delete all files and store all subdirectories.
Enumerate(directory, tokenSource)
.AsParallel()
.WithCancellation(tokenSource.Token)
.ForAll((FileSystemInfo item) =>
{
bool success = false;
try
{
// Remove the readonly attribute.
RemoveReadOnly(item);
// Check if the item is a file.
if (item is FileInfo)
{
// Delete the file.
item.Delete();
}
else
{
// Check if the item is a directory reparse point.
var subdirectory = item as DirectoryInfo;
ArgUtil.NotNull(subdirectory, nameof(subdirectory));
if (subdirectory.Attributes.HasFlag(FileAttributes.ReparsePoint))
{
try
{
// Delete the reparse point.
subdirectory.Delete();
}
catch (DirectoryNotFoundException)
{
// The target of the reparse point directory has been deleted.
// Therefore the item is no longer a directory and is now a file.
//
// Deletion of reparse point directories happens in parallel. This case can occur
// when reparse point directory FOO points to some other reparse point directory BAR,
// and BAR is deleted after the DirectoryInfo for FOO has already been initialized.
File.Delete(subdirectory.FullName);
}
}
else
{
// Store the directory.
directories.Push(subdirectory);
}
}
success = true;
}
catch (Exception) when (continueOnContentDeleteError)
{
// ignore any exception when continueOnContentDeleteError is true.
success = true;
}
finally
{
if (!success)
{
tokenSource.Cancel(); // Cancel is thread-safe.
}
}
});
}
catch (Exception)
{
tokenSource.Cancel();
throw;
}
}
// Delete the directories.
foreach (DirectoryInfo dir in directories.OrderByDescending(x => x.FullName.Length))
{
cancellationToken.ThrowIfCancellationRequested();
dir.Delete();
}
}
19
View Source File : FileContainerHttpClient.cs
License : MIT License
Project Creator : actions
License : MIT License
Project Creator : actions
[EditorBrowsable(EditorBrowsableState.Never)]
public async Task<HttpResponseMessage> UploadFileAsync(
Int64 containerId,
String itemPath,
Stream fileStream,
byte[] contentId,
Int64 fileLength,
Boolean isGzipped,
Guid scopeIdentifier,
CancellationToken cancellationToken = default(CancellationToken),
int chunkSize = c_defaultChunkSize,
int chunkRetryTimes = c_defaultChunkRetryTimes,
bool uploadFirstChunk = false,
Object userState = null)
{
if (containerId < 1)
{
throw new ArgumentException(WebApiResources.ContainerIdMustBeGreaterThanZero(), "containerId");
}
if (chunkSize > c_maxChunkSize)
{
chunkSize = c_maxChunkSize;
}
// if a contentId is specified but the chunk size is not a 2mb multiple error
if (contentId != null && (chunkSize % c_ContentChunkMultiple) != 0)
{
throw new ArgumentException(FileContainerResources.ChunksizeWrongWithContentId(c_ContentChunkMultiple), "chunkSize");
}
ArgumentUtility.CheckForNull(fileStream, "fileStream");
ApiResourceVersion gzipSupportedVersion = new ApiResourceVersion(new Version(1, 0), 2);
ApiResourceVersion requestVersion = await NegotiateRequestVersionAsync(FileContainerResourceIds.FileContainer, s_currentApiVersion, userState, cancellationToken).ConfigureAwait(false);
if (isGzipped
&& (requestVersion.ApiVersion < gzipSupportedVersion.ApiVersion
|| (requestVersion.ApiVersion == gzipSupportedVersion.ApiVersion && requestVersion.ResourceVersion < gzipSupportedVersion.ResourceVersion)))
{
throw new ArgumentException(FileContainerResources.GzipNotSupportedOnServer(), "isGzipped");
}
if (isGzipped && fileStream.Length >= fileLength)
{
throw new ArgumentException(FileContainerResources.BadCompression(), "fileLength");
}
HttpRequestMessage requestMessage = null;
List<KeyValuePair<String, String>> query = AppendItemQueryString(itemPath, scopeIdentifier);
if (fileStream.Length == 0)
{
// zero byte upload
FileUploadTrace(itemPath, $"Upload zero byte file '{itemPath}'.");
requestMessage = await CreateRequestMessageAsync(HttpMethod.Put, FileContainerResourceIds.FileContainer, routeValues: new { containerId = containerId }, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false);
return await SendAsync(requestMessage, userState, cancellationToken).ConfigureAwait(false);
}
bool multiChunk = false;
int totalChunks = 1;
if (fileStream.Length > chunkSize)
{
totalChunks = (int)Math.Ceiling(fileStream.Length / (double)chunkSize);
FileUploadTrace(itemPath, $"Begin chunking upload file '{itemPath}', chunk size '{chunkSize} Bytes', total chunks '{totalChunks}'.");
multiChunk = true;
}
else
{
FileUploadTrace(itemPath, $"File '{itemPath}' will be uploaded in one chunk.");
chunkSize = (int)fileStream.Length;
}
StreamParser streamParser = new StreamParser(fileStream, chunkSize);
SubStream currentStream = streamParser.GetNextStream();
HttpResponseMessage response = null;
Byte[] dataToSend = new Byte[chunkSize];
int currentChunk = 0;
Stopwatch uploadTimer = new Stopwatch();
while (currentStream.Length > 0 && !cancellationToken.IsCancellationRequested)
{
currentChunk++;
for (int attempt = 1; attempt <= chunkRetryTimes && !cancellationToken.IsCancellationRequested; attempt++)
{
if (attempt > 1)
{
TimeSpan backoff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10));
FileUploadTrace(itemPath, $"Backoff {backoff.TotalSeconds} seconds before attempt '{attempt}' chunk '{currentChunk}' of file '{itemPath}'.");
await Task.Delay(backoff, cancellationToken).ConfigureAwait(false);
currentStream.Seek(0, SeekOrigin.Begin);
}
FileUploadTrace(itemPath, $"Attempt '{attempt}' for uploading chunk '{currentChunk}' of file '{itemPath}'.");
// inorder for the upload to be retryable, we need the content to be re-readable
// to ensure this we copy the chunk into a byte array and send that
// chunk size ensures we can convert the length to an int
int bytesToCopy = (int)currentStream.Length;
using (MemoryStream ms = new MemoryStream(dataToSend))
{
await currentStream.CopyToAsync(ms, bytesToCopy, cancellationToken).ConfigureAwait(false);
}
// set the content and the Content-Range header
HttpContent byteArrayContent = new ByteArrayContent(dataToSend, 0, bytesToCopy);
byteArrayContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
byteArrayContent.Headers.ContentLength = currentStream.Length;
byteArrayContent.Headers.ContentRange = new System.Net.Http.Headers.ContentRangeHeaderValue(currentStream.StartingPostionOnOuterStream,
currentStream.EndingPostionOnOuterStream,
streamParser.Length);
FileUploadTrace(itemPath, $"Generate new HttpRequest for uploading file '{itemPath}', chunk '{currentChunk}' of '{totalChunks}'.");
try
{
if (requestMessage != null)
{
requestMessage.Dispose();
requestMessage = null;
}
requestMessage = await CreateRequestMessageAsync(
HttpMethod.Put,
FileContainerResourceIds.FileContainer,
routeValues: new { containerId = containerId },
version: s_currentApiVersion,
content: byteArrayContent,
queryParameters: query,
userState: userState,
cancellationToken: cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
// stop re-try on cancellation.
throw;
}
catch (Exception ex) when (attempt < chunkRetryTimes) // not the last attempt
{
FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' fail to create HttpRequest. Error: {ex.ToString()}.");
continue;
}
if (isGzipped)
{
//add gzip header info
byteArrayContent.Headers.ContentEncoding.Add("gzip");
byteArrayContent.Headers.Add("x-tfs-filelength", fileLength.ToString(System.Globalization.CultureInfo.InvariantCulture));
}
if (contentId != null)
{
byteArrayContent.Headers.Add("x-vso-contentId", Convert.ToBase64String(contentId)); // Base64FormattingOptions.None is default when not supplied
}
FileUploadTrace(itemPath, $"Start uploading file '{itemPath}' to server, chunk '{currentChunk}'.");
uploadTimer.Restart();
try
{
if (response != null)
{
response.Dispose();
response = null;
}
response = await SendAsync(requestMessage, userState, cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
{
// stop re-try on cancellation.
throw;
}
catch (Exception ex) when (attempt < chunkRetryTimes) // not the last attempt
{
FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' fail to send request to server. Error: {ex.ToString()}.");
continue;
}
uploadTimer.Stop();
FileUploadTrace(itemPath, $"Finished upload chunk '{currentChunk}' of file '{itemPath}', elapsed {uploadTimer.ElapsedMilliseconds} (ms), response code '{response.StatusCode}'.");
if (multiChunk)
{
FileUploadProgress(itemPath, currentChunk, (int)Math.Ceiling(fileStream.Length / (double)chunkSize));
}
if (response.IsSuccessStatusCode)
{
break;
}
else if (IsFastFailResponse(response))
{
FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' received non-success status code {response.StatusCode} for sending request and cannot continue.");
break;
}
else
{
FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' received non-success status code {response.StatusCode} for sending request.");
continue;
}
}
// if we don't have success then bail and return the failed response
if (!response.IsSuccessStatusCode)
{
break;
}
if (contentId != null && response.StatusCode == HttpStatusCode.Created)
{
// no need to keep uploading since the server said it has all the content
FileUploadTrace(itemPath, $"Stop chunking upload the rest of the file '{itemPath}', since server already has all the content.");
break;
}
currentStream = streamParser.GetNextStream();
if (uploadFirstChunk)
{
break;
}
}
cancellationToken.ThrowIfCancellationRequested();
return response;
}
19
View Source File : ActionHandlerAttributesFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private async Task<Doreplacedent> FixActionHandlerAttributes(Doreplacedent doreplacedent, TextSpan span, FixOption option, CancellationToken cancellation)
{
cancellation.ThrowIfCancellationRequested();
var root = await doreplacedent
.GetSyntaxRootAsync(cancellation)
.ConfigureAwait(false);
if (!(root?.FindNode(span) is MethodDeclarationSyntax node))
{
return doreplacedent;
}
var semanticModel = await doreplacedent
.GetSemanticModelAsync(cancellation)
.ConfigureAwait(false);
if (semanticModel == null)
{
return doreplacedent;
}
var pxContext = new PXContext(semanticModel.Compilation, codereplacedysisSettings: null);
var pxButtonAttributeList = pxContext.AttributeTypes.PXButtonAttribute.GetAttributeList();
var pxUIFieldAttributeList = pxContext.AttributeTypes.PXUIFieldAttribute.Type.GetAttributeList();
var attributeListCollection = new List<AttributeListSyntax>();
switch (option)
{
case FixOption.AddPXButtonAttribute:
attributeListCollection.Add(pxButtonAttributeList);
break;
case FixOption.AddPXUIFieldAttribute:
attributeListCollection.Add(pxUIFieldAttributeList);
break;
case FixOption.AddBothAttributes:
attributeListCollection.Add(pxButtonAttributeList);
attributeListCollection.Add(pxUIFieldAttributeList);
break;
}
var newNode = node.AddAttributeLists(attributeListCollection.ToArray());
var newRoot = root.ReplaceNode(node, newNode);
var newDoreplacedent = doreplacedent.WithSyntaxRoot(newRoot);
return newDoreplacedent;
}
19
View Source File : InternalApiCallsWalker.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private void ReportInternalApiDiagnostic(Location? location)
{
CancellationToken.ThrowIfCancellationRequested();
if (location == null || _reportedLocations.Contains(location))
return;
var internalApiDiagnostic = Diagnostic.Create(Descriptors.PX1076_CallToPXInternalUseOnlyAPI_OnlyISV, location);
_syntaxContext.ReportDiagnosticWithSuppressionCheck(internalApiDiagnostic, _pxContext.CodereplacedysisSettings);
_reportedLocations.Add(location);
}
19
View Source File : MultipleAttributesOnDacPropertyFixBase.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
public override SyntaxNode VisitAttributeList(AttributeListSyntax attributeListNode)
{
_cancellationToken.ThrowIfCancellationRequested();
if (_visitedAttributeListCounter < MaxVisitedAttributesCount)
_visitedAttributeListCounter++;
var attributesToCheck = attributeListNode.Attributes;
var modifiedAttributes = new List<AttributeSyntax>(attributesToCheck.Count);
foreach (AttributeSyntax attribute in attributesToCheck)
{
_cancellationToken.ThrowIfCancellationRequested();
if (!IsAttributeToRemove(attribute))
modifiedAttributes.Add(attribute);
}
bool allPreviousAttributeListWereRemoved = _attributeListsRemovedCounter > 0 &&
_attributeListsRemovedCounter == (_visitedAttributeListCounter - 1);
if (modifiedAttributes.Count == attributesToCheck.Count && !allPreviousAttributeListWereRemoved)
return attributeListNode;
else if (modifiedAttributes.Count == 0)
{
if (_attributeListsRemovedCounter < MaxRemovedAttributesCount)
{
_attributeListsRemovedCounter++;
}
return null;
}
AttributeListSyntax modifiedAttributeListNode = attributeListNode.WithAttributes(SyntaxFactory.SeparatedList(modifiedAttributes));
if (allPreviousAttributeListWereRemoved)
{
var trivia = modifiedAttributeListNode.GetLeadingTrivia().Prepend(SyntaxFactory.CarriageReturnLineFeed);
modifiedAttributeListNode = modifiedAttributeListNode.WithLeadingTrivia(trivia);
}
return modifiedAttributeListNode;
}
19
View Source File : MultipleAttributesOnDacPropertyFixBase.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
public bool IsAttributeToRemove(AttributeSyntax attributeNode)
{
if (attributeNode.Equals(_remainingAttribute))
return false;
ITypeSymbol attributeType = _semanticModel.GetTypeInfo(attributeNode, _cancellationToken).Type;
_cancellationToken.ThrowIfCancellationRequested();
if (attributeType == null)
return false;
var attributeInfos = _attributesRegister.GetFieldTypeAttributeInfos(attributeType);
return attributeInfos.Any(_attributeToRemovePredicate);
}
19
View Source File : MultipleKeysInDacFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private async Task<Doreplacedent> DeleteOtherPrimaryKeyDeclarationsFromDacAsync(Doreplacedent doreplacedent, IReadOnlyList<Location> locationsToRemove,
CancellationToken cancellation)
{
cancellation.ThrowIfCancellationRequested();
SyntaxNode root = await doreplacedent.GetSyntaxRootAsync(cancellation).ConfigureAwait(false);
if (root == null)
return doreplacedent;
var nodesToRemove = locationsToRemove.Select(location => root.FindNode(location.SourceSpan))
.OfType<ClreplacedDeclarationSyntax>();
var newRoot = root.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia | SyntaxRemoveOptions.KeepUnbalancedDirectives);
var newDoreplacedent = doreplacedent.WithSyntaxRoot(newRoot);
cancellation.ThrowIfCancellationRequested();
return newDoreplacedent;
}
19
View Source File : LocalizationMessageHelper.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private bool IsStringConcatenation()
{
Cancellation.ThrowIfCancellationRequested();
bool isStringAddition = _messageExpression is BinaryExpressionSyntax && _messageExpression.IsKind(SyntaxKind.AddExpression);
if (isStringAddition)
return true;
if (!(_messageExpression is InvocationExpressionSyntax i) || !(i.Expression is MemberAccessExpressionSyntax memberAccess) ||
memberAccess.Expression == null || memberAccess.Name == null)
return false;
ITypeSymbol stringType = SemanticModel.GetTypeInfo(memberAccess.Expression, Cancellation).Type;
if (stringType == null || stringType.SpecialType != SpecialType.System_String)
return false;
ISymbol stringMethod = SemanticModel.GetSymbolInfo(memberAccess.Name, Cancellation).Symbol;
if (stringMethod == null || (!_pxContext.StringFormat.Contains(stringMethod) && !_pxContext.StringConcat.Contains(stringMethod)))
return false;
return true;
}
19
View Source File : MissingTypeListAttributeFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private async Task<Doreplacedent> InsertTypeAttributeAsync(Doreplacedent doreplacedent, SyntaxNode root, PropertyDeclarationSyntax propertyDeclaration,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var semanticModel = await doreplacedent.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
IPropertySymbol property = semanticModel?.GetDeclaredSymbol(propertyDeclaration, cancellationToken);
if (property == null)
return doreplacedent;
var pxContext = new PXContext(semanticModel.Compilation, codereplacedysisSettings: null);
var lists = new List<INamedTypeSymbol> {
pxContext.AttributeTypes.PXIntListAttribute.Type,
pxContext.AttributeTypes.PXStringListAttribute.Type };
var attributeTypes = property.GetAttributes()
.Select(a => a.AttributeClreplaced);
var listAttribute = attributeTypes.FirstOrDefault(attributeType =>
lists.Any(lAttribute => attributeType.InheritsFromOrEquals(lAttribute, true)));
cancellationToken.ThrowIfCancellationRequested();
string attributeIdentifier = listAttribute.InheritsFromOrEquals(pxContext.AttributeTypes.PXIntListAttribute.Type)
? pxContext.FieldAttributes.PXIntAttribute.Name
: pxContext.FieldAttributes.PXStringAttribute.Name;
AttributeSyntax attributeNode =
SyntaxFactory.Attribute(
SyntaxFactory.IdentifierName(attributeIdentifier));
var attributes = propertyDeclaration.AttributeLists.Add(
SyntaxFactory.AttributeList(
SyntaxFactory.SingletonSeparatedList(attributeNode)));
var modifiedRoot = root.ReplaceNode(propertyDeclaration,
propertyDeclaration.WithAttributeLists(attributes));
return doreplacedent.WithSyntaxRoot(modifiedRoot);
}
19
View Source File : PXGraphCreationForBqlQueriesFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private Task<Doreplacedent> ReplaceIdentifier(Doreplacedent doreplacedent, SyntaxNode root, ArgumentSyntax nodeToReplace,
string identifierName, bool isGraphExtension, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
ExpressionSyntax newExpression;
if (identifierName == "this")
newExpression = SyntaxFactory.ThisExpression();
else
newExpression = SyntaxFactory.IdentifierName(identifierName);
if (isGraphExtension)
{
newExpression = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, newExpression,
SyntaxFactory.IdentifierName("Base"));
}
var newNode = nodeToReplace.WithExpression(newExpression);
var newRoot = root.ReplaceNode(nodeToReplace, newNode);
return Task.FromResult(doreplacedent.WithSyntaxRoot(newRoot));
}
19
View Source File : PXGraphDeclarationTypeParameterFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private async Task<Doreplacedent> FixGraphDeclarationTypeParameter(Doreplacedent doreplacedent, TextSpan span, CancellationToken cancellation)
{
cancellation.ThrowIfCancellationRequested();
var root = await doreplacedent
.GetSyntaxRootAsync(cancellation)
.ConfigureAwait(false);
if (!(root?.FindNode(span) is IdentifierNameSyntax invalidParameterTypeIdentifier))
{
return doreplacedent;
}
var clreplacedDeclaration = invalidParameterTypeIdentifier
.Ancestors()
.OfType<ClreplacedDeclarationSyntax>()
.FirstOrDefault();
if (clreplacedDeclaration == null)
{
return doreplacedent;
}
var invalidTypeParameterToken = invalidParameterTypeIdentifier.Identifier;
var validTypeParameterToken = clreplacedDeclaration.Identifier.WithTrailingTrivia();
var newRoot = root.ReplaceToken(invalidTypeParameterToken, validTypeParameterToken);
var newDoreplacedent = doreplacedent.WithSyntaxRoot(newRoot);
return newDoreplacedent;
}
19
View Source File : ThrowingExceptionsInDataViewDelegateAnalyzer.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private void CheckProcessingDelegates(PXGraphSemanticModel pxGraph, WalkerForGraphreplacedyzer walker, CancellationToken cancellation)
{
cancellation.ThrowIfCancellationRequested();
if (!pxGraph.IsProcessing)
{
return;
}
var processingViews = pxGraph.Views.Where(v => v.IsProcessing);
foreach (var viewDel in processingViews)
{
var finallyDelegates = viewDel.FinallyProcessDelegates.Where(d => d.Node != null);
foreach (var finDel in finallyDelegates)
{
cancellation.ThrowIfCancellationRequested();
walker.Visit(finDel.Node);
}
var parametersDelegates = viewDel.ParametersDelegates.Where(d => d.Node != null);
foreach (var parDel in parametersDelegates)
{
cancellation.ThrowIfCancellationRequested();
walker.Visit(parDel.Node);
}
var processDelegates = viewDel.ProcessDelegates.Where(d => d.Node != null);
foreach (var processDel in processDelegates)
{
cancellation.ThrowIfCancellationRequested();
walker.Visit(processDel.Node);
}
}
}
19
View Source File : ParametersCounterSyntaxWalker.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
public override void VisitGenericName(GenericNameSyntax genericNode)
{
_cancellationToken.ThrowIfCancellationRequested();
SymbolInfo symbolInfo = _syntaxContext.SemanticModel.GetSymbolInfo(genericNode, _cancellationToken);
if (!(symbolInfo.Symbol is ITypeSymbol typeSymbol))
{
_cancellationToken.ThrowIfCancellationRequested();
base.VisitGenericName(genericNode);
return;
}
if (genericNode.IsUnboundGenericName)
typeSymbol = typeSymbol.OriginalDefinition;
if (!ParametersCounter.CountParametersInTypeSymbolForGenericNode(typeSymbol, _cancellationToken))
return;
_cancellationToken.ThrowIfCancellationRequested();
base.VisitGenericName(genericNode);
}
19
View Source File : InternalApiCallsWalker.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
public override void VisitMemberBindingExpression(MemberBindingExpressionSyntax memberBinding)
{
CancellationToken.ThrowIfCancellationRequested();
SymbolInfo symbolInfo = _semanticModel.GetSymbolInfo(memberBinding, CancellationToken);
CheckNonTypeSymbol(symbolInfo, memberBinding);
base.VisitMemberBindingExpression(memberBinding);
}
19
View Source File : DacExtensionDefaultAttributeFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private async Task<Doreplacedent> AddToAttributePersistingCheckNothing(Doreplacedent doreplacedent, TextSpan span, bool isBoundField, CancellationToken cancellationToken)
{
SyntaxNode root = await doreplacedent.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
if (!(root?.FindNode(span) is AttributeSyntax attributeNode))
return doreplacedent;
if (!(attributeNode.Parent is AttributeListSyntax attributeList))
return doreplacedent;
cancellationToken.ThrowIfCancellationRequested();
SyntaxGenerator generator = SyntaxGenerator.GetGenerator(doreplacedent);
var memberAccessExpression = generator.MemberAccessExpression(generator.IdentifierName(TypeNames.PXPersistingCheck),
generator.IdentifierName(TypeNames.PersistingCheckNothing));
var persistingAttributeArgument = generator.AttributeArgument(TypeNames.PersistingCheck,
memberAccessExpression) as AttributeArgumentSyntax;
SyntaxNode modifiedRoot;
if (attributeNode.ArgumentList != null)
{
AttributeArgumentSyntax argument = GetArgumentFromAttribute();
if (argument != null)
{
persistingAttributeArgument = argument.ReplaceNode(argument.Expression, memberAccessExpression);
var newAttributeNode = attributeNode.ReplaceNode(argument, persistingAttributeArgument);
var newAttributeList = attributeList.ReplaceNode(attributeNode, newAttributeNode);
modifiedRoot = root.ReplaceNode(attributeList, newAttributeList);
}
else
{
var newAttributeList = generator.AddAttributeArguments(attributeNode, new SyntaxNode[] { persistingAttributeArgument }) as AttributeListSyntax;
modifiedRoot = root.ReplaceNode(attributeNode, newAttributeList.Attributes[0]);
}
}
else
{
AttributeListSyntax newAttribute = generator.InsertAttributeArguments(attributeNode, 1, new SyntaxNode[] { persistingAttributeArgument }) as AttributeListSyntax;
modifiedRoot = root.ReplaceNode(attributeNode, newAttribute.Attributes[0]);
}
return doreplacedent.WithSyntaxRoot(modifiedRoot);
AttributeArgumentSyntax GetArgumentFromAttribute()
{
foreach (AttributeArgumentSyntax _argument in attributeNode.ArgumentList.Arguments)
{
if (_argument.NameEquals != null
&& _argument.NameEquals.Name.Identifier.Text.Contains(TypeNames.PersistingCheck))
{
return _argument;
}
}
return null;
}
}
19
View Source File : DacPropertyAttributesAnalyzer.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private static List<(AttributeInfo Attribute, List<FieldTypeAttributeInfo> Infos)> GetFieldTypeAttributesInfos(ImmutableArray<AttributeInfo> attributes,
FieldTypeAttributesRegister fieldAttributesRegister,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
var fieldInfosList = new List<(AttributeInfo, List<FieldTypeAttributeInfo>)>(capacity: attributes.Length);
foreach (AttributeInfo attribute in attributes)
{
cancellationToken.ThrowIfCancellationRequested();
var attributeInfos = fieldAttributesRegister.GetFieldTypeAttributeInfos(attribute.AttributeData.AttributeClreplaced).ToList();
if (attributeInfos.Count > 0)
{
fieldInfosList.Add((attribute, attributeInfos));
}
}
return fieldInfosList;
}
19
View Source File : IncompatibleDacPropertyAndFieldAttributeFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private async Task<Doreplacedent> ChangePropertyTypeToAttributeType(Doreplacedent doreplacedent, SyntaxNode root, AttributeSyntax attributeNode,
PropertyDeclarationSyntax propertyNode, CancellationToken cancellationToken)
{
SemanticModel semanticModel = await doreplacedent.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
ITypeSymbol attributeType = semanticModel.GetTypeInfo(attributeNode, cancellationToken).Type;
cancellationToken.ThrowIfCancellationRequested();
if (attributeType == null)
return doreplacedent;
PXContext pxContext = new PXContext(semanticModel.Compilation, codereplacedysisSettings: null);
FieldTypeAttributesRegister typeAttributesRegister = new FieldTypeAttributesRegister(pxContext);
FieldTypeAttributeInfo? attributeInfo = typeAttributesRegister.GetFieldTypeAttributeInfos(attributeType)
.FirstOrDefault(attrInfo => attrInfo.IsFieldAttribute);
if (attributeInfo?.FieldType == null)
return doreplacedent;
SyntaxGenerator generator = SyntaxGenerator.GetGenerator(doreplacedent);
TypeSyntax replacingTypeNode = generator.TypeExpression(attributeInfo.Value.FieldType) as TypeSyntax;
if (attributeInfo.Value.FieldType.IsValueType)
{
replacingTypeNode = generator.NullableTypeExpression(replacingTypeNode) as TypeSyntax;
}
cancellationToken.ThrowIfCancellationRequested();
replacingTypeNode = replacingTypeNode.WithTrailingTrivia(propertyNode.Type.GetTrailingTrivia());
var propertyModified = propertyNode.WithType(replacingTypeNode);
var modifiedRoot = root.ReplaceNode(propertyNode, propertyModified);
return doreplacedent.WithSyntaxRoot(modifiedRoot);
}
19
View Source File : MultipleAttributesOnDacPropertyFixBase.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private Task<Doreplacedent> RemoveAllOtherAttributesFromPropertyAsync(Doreplacedent doreplacedent, SyntaxNode root, AttributeSyntax attributeNode,
PropertyDeclarationSyntax propertyDeclaration, SemanticModel semanticModel,
Func<FieldTypeAttributeInfo, bool> removePredicate, CancellationToken cancellationToken)
{
var rewriterWalker = new MultipleAttributesRemover(doreplacedent, semanticModel, attributeNode, removePredicate, cancellationToken);
var propertyModified = rewriterWalker.Visit(propertyDeclaration) as PropertyDeclarationSyntax;
cancellationToken.ThrowIfCancellationRequested();
var modifiedRoot = root.ReplaceNode(propertyDeclaration, propertyModified);
return Task.FromResult(doreplacedent.WithSyntaxRoot(modifiedRoot));
}
19
View Source File : IncorrectDeclarationOfDacKeyFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica
License : GNU General Public License v3.0
Project Creator : Acumatica
private async Task<Doreplacedent> ChangeKeyNameAsync(Doreplacedent doreplacedent, ClreplacedDeclarationSyntax dacNode, SyntaxNode root, ClreplacedDeclarationSyntax keyNode,
string newKeyName, bool shouldChangeLocation, CancellationToken cancellation)
{
cancellation.ThrowIfCancellationRequested();
ClreplacedDeclarationSyntax keyNodeWithNewName = keyNode.WithIdentifier(Identifier(newKeyName));
if (!shouldChangeLocation)
{
var newRoot = root.ReplaceNode(keyNode, keyNodeWithNewName);
return doreplacedent.WithSyntaxRoot(newRoot);
}
SyntaxNode trackingRoot = root.TrackNodes(dacNode, keyNode);
keyNode = trackingRoot.GetCurrentNode(keyNode);
if (keyNode == null)
return doreplacedent;
trackingRoot = trackingRoot.RemoveNode(keyNode, SyntaxRemoveOptions.KeepNoTrivia | SyntaxRemoveOptions.KeepUnbalancedDirectives);
cancellation.ThrowIfCancellationRequested();
dacNode = trackingRoot.GetCurrentNode(dacNode);
if (dacNode == null)
return doreplacedent;
var generator = SyntaxGenerator.GetGenerator(doreplacedent);
keyNodeWithNewName = keyNodeWithNewName.WithoutLeadingTrivia()
.WithTrailingTrivia(EndOfLine(Environment.NewLine), EndOfLine(Environment.NewLine))
.WithAdditionalAnnotations(Formatter.Annotation);
var newDacNode = generator.InsertMembers(dacNode, 0, keyNodeWithNewName);
trackingRoot = trackingRoot.ReplaceNode(dacNode, newDacNode);
var newDoreplacedent = doreplacedent.WithSyntaxRoot(trackingRoot);
var formattedDoreplacedent = await Formatter.FormatAsync(newDoreplacedent, Formatter.Annotation, cancellationToken: cancellation)
.ConfigureAwait(false);
return formattedDoreplacedent;
}
See More Examples