System.Threading.CancellationToken.ThrowIfCancellationRequested()

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 7

19 Source : ExpandableBufferWriter.cs
with MIT License
from 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 Source : ExpandableBufferWriter.cs
with MIT License
from 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 Source : CSRedisCache.cs
with MIT License
from 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 Source : CSRedisCache.cs
with MIT License
from 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 Source : CSRedisCache.cs
with MIT License
from 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 Source : CSRedisCache.cs
with MIT License
from 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 Source : CSRedisCache.cs
with MIT License
from 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 Source : RtmpServer.cs
with MIT License
from 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 Source : Supervisor.cs
with MIT License
from 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 Source : StreamHelper.cs
with MIT License
from 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 Source : TaskHelpers.cs
with MIT License
from 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 Source : MixedRealityToolkitFiles.cs
with Apache License 2.0
from 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 Source : CategoryTreeBuilder.cs
with Apache License 2.0
from 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 Source : CategoryTreeBuilder.cs
with Apache License 2.0
from 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 Source : KeywordCollectionBuilder.cs
with Apache License 2.0
from 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 Source : KeywordCollectionBuilder.cs
with Apache License 2.0
from 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 Source : FunctionalExtensions.cs
with MIT License
from 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 Source : FunctionalExtensions.cs
with MIT License
from 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 Source : FunctionalExtensions.cs
with MIT License
from 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 Source : FunctionalExtensions.cs
with MIT License
from 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 Source : RecordFSRepo.cs
with Apache License 2.0
from 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 Source : MessageListener.cs
with MIT License
from 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 Source : StreamString.cs
with MIT License
from 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 Source : StreamString.cs
with MIT License
from 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 Source : FileContainerServer.cs
with MIT License
from 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 Source : FileContainerServer.cs
with MIT License
from 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 Source : MessageListener.cs
with MIT License
from 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 Source : GitSourceProvider.cs
with MIT License
from 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 Source : IOUtil.cs
with MIT License
from 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 Source : ProcessInvoker.cs
with MIT License
from 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 Source : GitSourceProvider.cs
with MIT License
from 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 Source : IOUtil.cs
with MIT License
from 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 Source : FileContainerHttpClient.cs
with MIT License
from 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 Source : ActionHandlerAttributesFix.cs
with GNU General Public License v3.0
from 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 Source : InternalApiCallsWalker.cs
with GNU General Public License v3.0
from 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 Source : MultipleAttributesOnDacPropertyFixBase.cs
with GNU General Public License v3.0
from 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 Source : MultipleAttributesOnDacPropertyFixBase.cs
with GNU General Public License v3.0
from 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 Source : MultipleKeysInDacFix.cs
with GNU General Public License v3.0
from 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 Source : LocalizationMessageHelper.cs
with GNU General Public License v3.0
from 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 Source : MissingTypeListAttributeFix.cs
with GNU General Public License v3.0
from 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 Source : PXGraphCreationForBqlQueriesFix.cs
with GNU General Public License v3.0
from 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 Source : PXGraphDeclarationTypeParameterFix.cs
with GNU General Public License v3.0
from 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 Source : ThrowingExceptionsInDataViewDelegateAnalyzer.cs
with GNU General Public License v3.0
from 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 Source : ParametersCounterSyntaxWalker.cs
with GNU General Public License v3.0
from 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 Source : InternalApiCallsWalker.cs
with GNU General Public License v3.0
from Acumatica

public override void VisitMemberBindingExpression(MemberBindingExpressionSyntax memberBinding)
		{
			CancellationToken.ThrowIfCancellationRequested();

			SymbolInfo symbolInfo = _semanticModel.GetSymbolInfo(memberBinding, CancellationToken);

			CheckNonTypeSymbol(symbolInfo, memberBinding);
			base.VisitMemberBindingExpression(memberBinding);
		}

19 Source : DacExtensionDefaultAttributeFix.cs
with GNU General Public License v3.0
from 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 Source : DacPropertyAttributesAnalyzer.cs
with GNU General Public License v3.0
from 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 Source : IncompatibleDacPropertyAndFieldAttributeFix.cs
with GNU General Public License v3.0
from 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 Source : MultipleAttributesOnDacPropertyFixBase.cs
with GNU General Public License v3.0
from 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 Source : IncorrectDeclarationOfDacKeyFix.cs
with GNU General Public License v3.0
from 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