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 View Source File : ExpandableBufferWriter.cs
License : MIT License
Project Creator : 1996v

public async Task CopyToAsync(Stream stream, CancellationToken CancellationToken)
        {
            if (Buffered > 0)
            {
                FlushLastSpanBoundary();
                for (int i = 0; i < complexBuffer.Spans.Length; i++)
                {
                    if (bufferedsRelativeSpan[i] != 0)
                    {
                        CancellationToken.ThrowIfCancellationRequested();
                        await complexBuffer.Spans[i].WriteToAsync(stream, bufferedsRelativeSpan[i]).ConfigureAwait(false);
                    }
                }
            }
        }

19 View Source File : ExpandableBufferWriter.cs
License : MIT License
Project Creator : 1996v

public void CopyTo(Stream stream, CancellationToken CancellationToken)
        {
            if (Buffered > 0)
            {
                FlushLastSpanBoundary();
                for (int i = 0; i < complexBuffer.Spans.Length; i++)
                {
                    if (bufferedsRelativeSpan[i] != 0)
                    {
                        CancellationToken.ThrowIfCancellationRequested();
                        complexBuffer.Spans[i].WriteTo(stream, bufferedsRelativeSpan[i]);
                    }
                }
            }
        }

19 View Source File : CSRedisCache.cs
License : MIT License
Project Creator : 2881099

public async Task<byte[]> GetAsync(string key, CancellationToken token = default(CancellationToken)) {
			if (key == null) {
				throw new ArgumentNullException(nameof(key));
			}

			token.ThrowIfCancellationRequested();

			return await GetAndRefreshAsync(key, getData: true, token: token);
		}

19 View Source File : CSRedisCache.cs
License : MIT License
Project Creator : 2881099

public async Task SetAsync(string key, byte[] value, DistributedCacheEntryOptions options, CancellationToken token = default(CancellationToken)) {
			if (key == null) {
				throw new ArgumentNullException(nameof(key));
			}

			if (value == null) {
				throw new ArgumentNullException(nameof(value));
			}

			if (options == null) {
				throw new ArgumentNullException(nameof(options));
			}

			token.ThrowIfCancellationRequested();

			var creationTime = DateTimeOffset.UtcNow;

			var absoluteExpiration = GetAbsoluteExpiration(creationTime, options);
			await _redisClient.EvalAsync(SetScript, key,
				new object[]
				{
						absoluteExpiration?.Ticks ?? NotPresent,
						options.SlidingExpiration?.Ticks ?? NotPresent,
						GetExpirationInSeconds(creationTime, absoluteExpiration, options) ?? NotPresent,
						value
				});
		}

19 View Source File : CSRedisCache.cs
License : MIT License
Project Creator : 2881099

private async Task RefreshAsync(string key, DateTimeOffset? absExpr, TimeSpan? sldExpr, CancellationToken token = default(CancellationToken)) {
			if (key == null) {
				throw new ArgumentNullException(nameof(key));
			}

			token.ThrowIfCancellationRequested();

			// Note Refresh has no effect if there is just an absolute expiration (or neither).
			TimeSpan? expr = null;
			if (sldExpr.HasValue) {
				if (absExpr.HasValue) {
					var relExpr = absExpr.Value - DateTimeOffset.Now;
					expr = relExpr <= sldExpr.Value ? relExpr : sldExpr;
				} else {
					expr = sldExpr;
				}
				await _redisClient.ExpireAsync(key, expr ?? TimeSpan.Zero);
				// TODO: Error handling
			}
		}

19 View Source File : CSRedisCache.cs
License : MIT License
Project Creator : 2881099

public async Task RefreshAsync(string key, CancellationToken token = default(CancellationToken)) {
			if (key == null) {
				throw new ArgumentNullException(nameof(key));
			}

			token.ThrowIfCancellationRequested();

			await GetAndRefreshAsync(key, getData: false, token: token);
		}

19 View Source File : CSRedisCache.cs
License : MIT License
Project Creator : 2881099

private async Task<byte[]> GetAndRefreshAsync(string key, bool getData, CancellationToken token = default(CancellationToken)) {
			if (key == null) {
				throw new ArgumentNullException(nameof(key));
			}

			token.ThrowIfCancellationRequested();

			// This also resets the LRU status as desired.
			// TODO: Can this be done in one operation on the server side? Probably, the trick would just be the DateTimeOffset math.
			object[] results;
			byte[] value = null;
			if (getData) {
				var ret = await _redisClient.HMGetAsync<byte[]>(key, AbsoluteExpirationKey, SlidingExpirationKey, DataKey);
				results = new object[] { ret[0] == null ? null : Encoding.UTF8.GetString(ret[0]), ret[1] == null ? null : Encoding.UTF8.GetString(ret[1]), value = ret[2] };
			} else {
				results = await _redisClient.HMGetAsync(key, AbsoluteExpirationKey, SlidingExpirationKey);
			}

			// TODO: Error handling
			if (results.Length >= 2) {
				MapMetadata(results, out DateTimeOffset? absExpr, out TimeSpan? sldExpr);
				await RefreshAsync(key, absExpr, sldExpr, token);
			}

			if (results.Length >= 3) {
				return value;
			}

			return null;
		}

19 View Source File : RtmpServer.cs
License : MIT License
Project Creator : a1q123456

public Task StartAsync(CancellationToken ct = default)
        {
            if (Started)
            {
                throw new InvalidOperationException("already started");
            }
            _webSocketServer?.Start(c =>
            {
                var session = new WebSocketSession(c, _webSocketOptions);
                c.OnOpen = session.HandleOpen;
                c.OnClose = session.HandleClose;
                c.OnMessage = session.HandleMessage;
            });

            if (_webSocketServer != null)
            {
                CancellationTokenRegistration reg = default;
                reg = ct.Register(() =>
                {
                    reg.Dispose();
                    _webSocketServer.Dispose();
                    _webSocketServer = new WebSocketServer(_webSocketOptions.BindEndPoint.ToString());
                });
            }
            Started = true;
            var ret = new TaskCompletionSource<int>();
            var t = new Thread(o =>
            {
                try
                {
                    while (!ct.IsCancellationRequested)
                    {
                        try
                        {
                            _allDone.Reset();
                            _listener.BeginAccept(new AsyncCallback(ar =>
                            {
                                AcceptCallback(ar, ct);
                            }), _listener);
                            while (!_allDone.WaitOne(1))
                            {
                                ct.ThrowIfCancellationRequested();
                            }
                        }
                        catch (OperationCanceledException)
                        {
                            throw;
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.ToString());
                        }
                    }
                }
                catch (OperationCanceledException) { }
                finally
                {
                    ret.SetResult(1);
                }
            });

            t.Start();
            return ret.Task;
        }

19 View Source File : Supervisor.cs
License : MIT License
Project Creator : a1q123456

private void ThreadEntry()
        {
            try
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    foreach (var kv in server.connectedSessions)
                    {
                        if (!sessionStates.TryGetValue(kv.Key, out var sessionState))
                        {
                            sessionState = new SessionState()
                            {
                                LastPing = DateTime.Now,
                                Session = kv.Value
                            };
                            sessionStates.Add(kv.Key, sessionState);
                        }
                        var session = kv.Value;
                        if (DateTime.Now - sessionState.LastPing >= pingInterval && sessionState.CancellationTokenSource == null)
                        {
                            sessionState.CancellationTokenSource = new CancellationTokenSource();
                            sessionState.CancellationTokenSource.CancelAfter((int)responseThreshole.TotalMilliseconds);
                            var pingTask = session.PingAsync(sessionState.CancellationTokenSource.Token);
                            pingTask.ContinueWith(tsk =>
                            {
                                sessionState.CancellationTokenSource.Dispose();
                                sessionState.CancellationTokenSource = null;
                                sessionState.LastPing = DateTime.Now;
                            }, TaskContinuationOptions.OnlyOnRanToCompletion);
                            pingTask.ContinueWith(tsk =>
                            {
                                sessionState.Session.Disconnect(new ExceptionalEventArgs("pingpong timeout"));
                                sessionState.CancellationTokenSource.Dispose();
                                sessionState.CancellationTokenSource = null;
                            }, TaskContinuationOptions.OnlyOnCanceled);
                        }
                    }
                    Thread.Sleep(1);
                    cancellationToken.ThrowIfCancellationRequested();
                }
            }
            catch
            {

            }
        }

19 View Source File : StreamHelper.cs
License : MIT License
Project Creator : a1q123456

public static async Task ReadBytesAsync(this Stream stream, Memory<byte> buffer, CancellationToken ct = default)
        {
            int count = buffer.Length;
            var offset = 0;
            while (count != 0)
            {
                var n = await stream.ReadAsync(buffer.Slice(offset, count), ct);
                ct.ThrowIfCancellationRequested();
                if (n == 0)
                {
                    break;
                }
                offset += n;
                count -= n;
            }

            if (offset != buffer.Length)
            {
                throw new EndOfStreamException();
            }
        }

19 View Source File : TaskHelpers.cs
License : MIT License
Project Creator : abdullin

public static Func<TSource, CancellationToken, TResult> WithCancellation<TSource, TResult>([NotNull] Func<TSource, TResult> lambda)
		{
			Contract.Requires(lambda != null);
			return (value, ct) =>
			{
				if (ct.IsCancellationRequested) ct.ThrowIfCancellationRequested();
				return lambda(value);
			};
		}

19 View Source File : MixedRealityToolkitFiles.cs
License : Apache License 2.0
Project Creator : abist-co-ltd

private static void SearchForFolders(string rootPath, CancellationToken ct)
        {
            try
            {
                var filePathResults = Directory.GetFiles(rootPath, SentinelFilePattern, SearchOption.AllDirectories);
                foreach (var sentinelFilePath in filePathResults)
                {
                    TryRegisterModuleViaFile(sentinelFilePath);

                    if (ct.IsCancellationRequested)
                    {
                        ct.ThrowIfCancellationRequested();
                    }
                }

                // Create the Generated folder, if the user tries to delete the Generated folder it will be created again
                TryToCreateGeneratedFolder();
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine($"\n{nameof(OperationCanceledException)} thrown\n");
            }
            catch (Exception ex)
            {
                Debug.LogError(ex.Message);
            }
        }

19 View Source File : CategoryTreeBuilder.cs
License : Apache License 2.0
Project Creator : acblog

public static async Task<(CategoryTree, IReadOnlyDictionary<CategoryTree.CategoryTreeNode, IList<Post>>)> BuildFromPosts(IAsyncEnumerable<Post> data, CancellationToken cancellationToken = default)
        {
            CategoryTree.CategoryTreeNode root = new CategoryTree.CategoryTreeNode(new Category());
            Dictionary<CategoryTree.CategoryTreeNode, IList<Post>> map = new Dictionary<CategoryTree.CategoryTreeNode, IList<Post>>();
            await foreach (var v in data)
            {
                cancellationToken.ThrowIfCancellationRequested();
                CategoryTree.CategoryTreeNode node = root;
                foreach (var k in v.Category.Items)
                {
                    if (!node.Children.ContainsKey(k))
                    {
                        CategoryBuilder cb = new CategoryBuilder();
                        cb.AddSubCategory(node.Category.Items.Concat(new[] { k }).ToArray());
                        Category c = cb.Build();
                        var tn = new CategoryTree.CategoryTreeNode(c);
                        map.Add(tn, new List<Post>());
                        node.Children.Add(k, tn);
                        node = tn;
                    }
                    else
                    {
                        node = node.Children[k];
                    }
                    map[node].Add(v);
                }
            }
            return (new CategoryTree(root), map);
        }

19 View Source File : CategoryTreeBuilder.cs
License : Apache License 2.0
Project Creator : acblog

public static async Task<CategoryTree> Build(IAsyncEnumerable<Category> data, CancellationToken cancellationToken = default)
        {
            CategoryTree.CategoryTreeNode root = new CategoryTree.CategoryTreeNode(new Category());
            await foreach (var v in data)
            {
                cancellationToken.ThrowIfCancellationRequested();
                CategoryTree.CategoryTreeNode node = root;
                foreach (var k in v.Items)
                {
                    if (!node.Children.ContainsKey(k))
                    {
                        CategoryBuilder cb = new CategoryBuilder();
                        cb.AddSubCategory(node.Category.Items.Concat(new[] { k }).ToArray());
                        Category c = cb.Build();
                        var tn = new CategoryTree.CategoryTreeNode(c);
                        node.Children.Add(k, tn);
                        node = tn;
                    }
                    else
                    {
                        node = node.Children[k];
                    }
                }
            }
            return new CategoryTree(root);
        }

19 View Source File : KeywordCollectionBuilder.cs
License : Apache License 2.0
Project Creator : acblog

public static async Task<(KeywordCollection, IReadOnlyDictionary<string, IList<Post>>)> BuildFromPosts(IAsyncEnumerable<Post> data, CancellationToken cancellationToken = default)
        {
            Dictionary<string, IList<Post>> dict = new Dictionary<string, IList<Post>>();
            await foreach (var v in data)
            {
                cancellationToken.ThrowIfCancellationRequested();
                List<string> keyids = new List<string>();
                foreach (var k in v.Keywords.Items)
                {
                    if (!dict.ContainsKey(k))
                    {
                        var list = new List<Post>
                        {
                            v
                        };
                        dict.Add(k, list);
                    }
                    else
                    {
                        dict[k].Add(v);
                    }
                }
            }
            return (new KeywordCollection(dict.Select(pair => new Keyword { Items = new string[] { pair.Key } }).ToList()), dict);
        }

19 View Source File : KeywordCollectionBuilder.cs
License : Apache License 2.0
Project Creator : acblog

public static async Task<KeywordCollection> Build(IAsyncEnumerable<Keyword> data, CancellationToken cancellationToken = default)
        {
            HashSet<string> res = new HashSet<string>();
            await foreach (var v in data)
            {
                cancellationToken.ThrowIfCancellationRequested();
                List<string> keyids = new List<string>();
                foreach (var k in v.Items)
                {
                    res.Add(k);
                }
            }
            return new KeywordCollection(res.Select(pair => new Keyword { Items = new string[] { pair } }).ToList());
        }

19 View Source File : FunctionalExtensions.cs
License : MIT License
Project Creator : Accelerider

public static Func<TInput, Task<T>> ThenAsync<TInput, TOutput, T>(
            this Func<TInput, Task<TOutput>> @this,
            Func<TOutput, T> function,
            CancellationToken cancellationToken = default)
        {
            ThrowIfNull(function);

            return async input =>
            {
                cancellationToken.ThrowIfCancellationRequested();
                var output = await @this(input);

                return function(output);
            };
        }

19 View Source File : FunctionalExtensions.cs
License : MIT License
Project Creator : Accelerider

public static Func<TInput, Task<IEnumerable<T>>> ThenAsync<TInput, TOutput, T>(
            this Func<TInput, Task<IEnumerable<TOutput>>> @this,
            Func<TOutput, T> function,
            CancellationToken cancellationToken = default)
        {
            ThrowIfNull(function);

            return async input =>
            {
                cancellationToken.ThrowIfCancellationRequested();
                var output = await @this(input);

                return output.Select(item =>
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    return function(item);
                });
            };
        }

19 View Source File : FunctionalExtensions.cs
License : MIT License
Project Creator : Accelerider

public static Func<TInput, Task<T>> ThenAsync<TInput, TOutput, T>(
            this Func<TInput, Task<TOutput>> @this,
            Func<TOutput, Task<T>> function,
            CancellationToken cancellationToken = default)
        {
            ThrowIfNull(function);

            return async input =>
            {
                cancellationToken.ThrowIfCancellationRequested();
                var output = await @this(input);

                return await function(output);
            };
        }

19 View Source File : FunctionalExtensions.cs
License : MIT License
Project Creator : Accelerider

public static Func<TInput, Task<IEnumerable<T>>> ThenAsync<TInput, TOutput, T>(
            this Func<TInput, Task<IEnumerable<TOutput>>> @this,
            Func<TOutput, Task<T>> function,
            CancellationToken cancellationToken = default)
        {
            ThrowIfNull(function);

            return async input =>
            {
                cancellationToken.ThrowIfCancellationRequested();
                var output = await @this(input);

                var result = new List<T>();
                foreach (var item in output)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    result.Add(await function(item));
                }

                return result;
            };
        }

19 View Source File : RecordFSRepo.cs
License : Apache License 2.0
Project Creator : acblog

public override IAsyncEnumerable<string> All(CancellationToken cancellationToken = default)
        {
            IEnumerable<string> Inner()
            {
                foreach (var file in Directory.EnumerateFiles(RootPath, "*.md", SearchOption.AllDirectories))
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var name = Path.GetRelativePath(RootPath, file);
                    yield return name[0..^3].Replace('\\', '/');
                }
            }
            return Inner().ToAsyncEnumerable();
        }

19 View Source File : MessageListener.cs
License : MIT License
Project Creator : actions

public async Task<Boolean> CreateSessionAsync(CancellationToken token)
        {
            Trace.Entering();

            // Settings
            var configManager = HostContext.GetService<IConfigurationManager>();
            _settings = configManager.LoadSettings();
            var serverUrl = _settings.ServerUrl;
            Trace.Info(_settings);

            // Create connection.
            Trace.Info("Loading Credentials");
            var credMgr = HostContext.GetService<ICredentialManager>();
            VssCredentials creds = credMgr.LoadCredentials();

            var agent = new TaskAgentReference
            {
                Id = _settings.AgentId,
                Name = _settings.AgentName,
                Version = BuildConstants.RunnerPackage.Version,
                OSDescription = RuntimeInformation.OSDescription,
            };
            string sessionName = $"{Environment.MachineName ?? "RUNNER"}";
            var taskAgentSession = new TaskAgentSession(sessionName, agent);

            string errorMessage = string.Empty;
            bool encounteringError = false;

            while (true)
            {
                token.ThrowIfCancellationRequested();
                Trace.Info($"Attempt to create session.");
                try
                {
                    Trace.Info("Connecting to the Runner Server...");
                    await _runnerServer.ConnectAsync(new Uri(serverUrl), creds);
                    Trace.Info("VssConnection created");

                    _term.WriteLine();
                    _term.WriteSuccessMessage("Connected to GitHub");
                    _term.WriteLine();

                    _session = await _runnerServer.CreateAgentSessionAsync(
                                                        _settings.PoolId,
                                                        taskAgentSession,
                                                        token);

                    Trace.Info($"Session created.");
                    if (encounteringError)
                    {
                        _term.WriteLine($"{DateTime.UtcNow:u}: Runner reconnected.");
                        _sessionCreationExceptionTracker.Clear();
                        encounteringError = false;
                    }

                    return true;
                }
                catch (OperationCanceledException) when (token.IsCancellationRequested)
                {
                    Trace.Info("Session creation has been cancelled.");
                    throw;
                }
                catch (TaskAgentAccessTokenExpiredException)
                {
                    Trace.Info("Runner OAuth token has been revoked. Session creation failed.");
                    throw;
                }
                catch (Exception ex)
                {
                    Trace.Error("Catch exception during create session.");
                    Trace.Error(ex);

                    if (ex is VssOAuthTokenRequestException && creds.Federated is VssOAuthCredential vssOAuthCred)
                    {
                        // Check whether we get 401 because the runner registration already removed by the service.
                        // If the runner registration get deleted, we can't exchange oauth token.
                        Trace.Error("Test oauth app registration.");
                        var oauthTokenProvider = new VssOAuthTokenProvider(vssOAuthCred, new Uri(serverUrl));
                        var authError = await oauthTokenProvider.ValidateCredentialAsync(token);
                        if (string.Equals(authError, "invalid_client", StringComparison.OrdinalIgnoreCase))
                        {
                            _term.WriteError("Failed to create a session. The runner registration has been deleted from the server, please re-configure.");
                            return false;
                        }
                    }

                    if (!IsSessionCreationExceptionRetriable(ex))
                    {
                        _term.WriteError($"Failed to create session. {ex.Message}");
                        return false;
                    }

                    if (!encounteringError) //print the message only on the first error
                    {
                        _term.WriteError($"{DateTime.UtcNow:u}: Runner connect error: {ex.Message}. Retrying until reconnected.");
                        encounteringError = true;
                    }

                    Trace.Info("Sleeping for {0} seconds before retrying.", _sessionCreationRetryInterval.TotalSeconds);
                    await HostContext.Delay(_sessionCreationRetryInterval, token);
                }
            }
        }

19 View Source File : StreamString.cs
License : MIT License
Project Creator : actions

public async Task<Int32> ReadInt32Async(CancellationToken cancellationToken)
        {
            byte[] readBytes = new byte[sizeof(Int32)];
            int dataread = 0;
            while (sizeof(Int32) - dataread > 0 && (!cancellationToken.IsCancellationRequested))
            {
                Task<int> op = _ioStream.ReadAsync(readBytes, dataread, sizeof(Int32) - dataread, cancellationToken);
                int newData = 0;
                newData = await op.WithCancellation(cancellationToken);
                dataread += newData;
                if (0 == newData)
                {
                    await Task.Delay(100, cancellationToken);
                }
            }

            cancellationToken.ThrowIfCancellationRequested();
            return BitConverter.ToInt32(readBytes, 0);
        }

19 View Source File : StreamString.cs
License : MIT License
Project Creator : actions

public async Task WriteStringAsync(string outString, CancellationToken cancellationToken)
        {
            byte[] outBuffer = streamEncoding.GetBytes(outString);
            Int32 len = outBuffer.Length;
            if (len > MaxStringSize)
            {
                throw new ArgumentOutOfRangeException();
            }

            await WriteInt32Async(len, cancellationToken);
            cancellationToken.ThrowIfCancellationRequested();
            Task op = _ioStream.WriteAsync(outBuffer, 0, len, cancellationToken);
            await op.WithCancellation(cancellationToken);
            op = _ioStream.FlushAsync(cancellationToken);
            await op.WithCancellation(cancellationToken);
        }

19 View Source File : FileContainerServer.cs
License : MIT License
Project Creator : actions

private async Task<DownloadResult> DownloadAsync(RunnerActionPluginExecutionContext context, int downloaderId, CancellationToken token)
        {
            List<DownloadInfo> failedFiles = new List<DownloadInfo>();
            Stopwatch downloadTimer = new Stopwatch();
            while (_fileDownloadQueue.TryDequeue(out DownloadInfo fileToDownload))
            {
                token.ThrowIfCancellationRequested();
                try
                {
                    int retryCount = 0;
                    bool downloadFailed = false;
                    while (true)
                    {
                        try
                        {
                            context.Debug($"Start downloading file: '{fileToDownload.ItemPath}' (Downloader {downloaderId})");
                            downloadTimer.Restart();
                            using (FileStream fs = new FileStream(fileToDownload.LocalPath, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize: _defaultFileStreamBufferSize, useAsync: true))
                            using (var downloadStream = await _fileContainerHttpClient.DownloadFileAsync(_containerId, fileToDownload.ItemPath, token, _projectId))
                            {
                                await downloadStream.CopyToAsync(fs, _defaultCopyBufferSize, token);
                                await fs.FlushAsync(token);
                                downloadTimer.Stop();
                                context.Debug($"File: '{fileToDownload.LocalPath}' took {downloadTimer.ElapsedMilliseconds} milliseconds to finish download (Downloader {downloaderId})");
                                break;
                            }
                        }
                        catch (OperationCanceledException) when (token.IsCancellationRequested)
                        {
                            context.Debug($"Download has been cancelled while downloading {fileToDownload.ItemPath}. (Downloader {downloaderId})");
                            throw;
                        }
                        catch (Exception ex)
                        {
                            retryCount++;
                            context.Warning($"Fail to download '{fileToDownload.ItemPath}', error: {ex.Message} (Downloader {downloaderId})");
                            context.Debug(ex.ToString());
                        }

                        if (retryCount < 3)
                        {
                            var backOff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(30));
                            context.Warning($"Back off {backOff.TotalSeconds} seconds before retry. (Downloader {downloaderId})");
                            await Task.Delay(backOff);
                        }
                        else
                        {
                            // upload still failed after 3 tries.
                            downloadFailed = true;
                            break;
                        }
                    }

                    if (downloadFailed)
                    {
                        // tracking file that failed to download.
                        failedFiles.Add(fileToDownload);
                    }

                    Interlocked.Increment(ref _downloadFilesProcessed);
                }
                catch (Exception ex)
                {
                    // We should never
                    context.Error($"Error '{ex.Message}' when downloading file '{fileToDownload}'. (Downloader {downloaderId})");
                    throw ex;
                }
            }

            return new DownloadResult(failedFiles);
        }

19 View Source File : FileContainerServer.cs
License : MIT License
Project Creator : actions

private async Task<UploadResult> UploadAsync(RunnerActionPluginExecutionContext context, int uploaderId, CancellationToken token)
        {
            List<string> failedFiles = new List<string>();
            long uploadedSize = 0;
            string fileToUpload;
            Stopwatch uploadTimer = new Stopwatch();
            while (_fileUploadQueue.TryDequeue(out fileToUpload))
            {
                token.ThrowIfCancellationRequested();
                try
                {
                    using (FileStream fs = File.Open(fileToUpload, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        string itemPath = (_containerPath.TrimEnd('/') + "/" + fileToUpload.Remove(0, _sourceParentDirectory.Length + 1)).Replace('\\', '/');
                        bool failAndExit = false;
                        try
                        {
                            uploadTimer.Restart();
                            using (HttpResponseMessage response = await _fileContainerHttpClient.UploadFileAsync(_containerId, itemPath, fs, _projectId, cancellationToken: token, chunkSize: 4 * 1024 * 1024))
                            {
                                if (response == null || response.StatusCode != HttpStatusCode.Created)
                                {
                                    context.Output($"Unable to copy file to server StatusCode={response?.StatusCode}: {response?.ReasonPhrase}. Source file path: {fileToUpload}. Target server path: {itemPath}");

                                    if (response?.StatusCode == HttpStatusCode.Conflict)
                                    {
                                        // fail upload task but continue with any other files
                                        context.Error($"Error '{fileToUpload}' has already been uploaded.");
                                    }
                                    else if (_fileContainerHttpClient.IsFastFailResponse(response))
                                    {
                                        // Fast fail: we received an http status code where we should abandon our efforts
                                        context.Output($"Cannot continue uploading files, so draining upload queue of {_fileUploadQueue.Count} items.");
                                        DrainUploadQueue(context);
                                        failedFiles.Clear();
                                        failAndExit = true;
                                        throw new UploadFailedException($"Critical failure uploading '{fileToUpload}'");
                                    }
                                    else
                                    {
                                        context.Debug($"Adding '{fileToUpload}' to retry list.");
                                        failedFiles.Add(fileToUpload);
                                    }
                                    throw new UploadFailedException($"Http failure response '{response?.StatusCode}': '{response?.ReasonPhrase}' while uploading '{fileToUpload}'");
                                }

                                uploadTimer.Stop();
                                context.Debug($"File: '{fileToUpload}' took {uploadTimer.ElapsedMilliseconds} milliseconds to finish upload");
                                uploadedSize += fs.Length;
                                OutputLogForFile(context, fileToUpload, $"Detail upload trace for file: {itemPath}", context.Debug);
                            }
                        }
                        catch (OperationCanceledException) when (token.IsCancellationRequested)
                        {
                            context.Output($"File upload has been cancelled during upload file: '{fileToUpload}'.");
                            throw;
                        }
                        catch (Exception ex)
                        {
                            context.Output($"Fail to upload '{fileToUpload}' due to '{ex.Message}'.");
                            context.Output(ex.ToString());

                            OutputLogForFile(context, fileToUpload, $"Detail upload trace for file that fail to upload: {itemPath}", context.Output);

                            if (failAndExit)
                            {
                                context.Debug("Exiting upload.");
                                throw;
                            }
                        }
                    }

                    Interlocked.Increment(ref _uploadFilesProcessed);
                }
                catch (Exception ex)
                {
                    context.Output($"File error '{ex.Message}' when uploading file '{fileToUpload}'.");
                    throw ex;
                }
            }

            return new UploadResult(failedFiles, uploadedSize);
        }

19 View Source File : MessageListener.cs
License : MIT License
Project Creator : actions

public async Task<TaskAgentMessage> GetNextMessageAsync(CancellationToken token)
        {
            Trace.Entering();
            ArgUtil.NotNull(_session, nameof(_session));
            ArgUtil.NotNull(_settings, nameof(_settings));
            bool encounteringError = false;
            int continuousError = 0;
            string errorMessage = string.Empty;
            Stopwatch heartbeat = new Stopwatch();
            heartbeat.Restart();
            while (true)
            {
                token.ThrowIfCancellationRequested();
                TaskAgentMessage message = null;
                try
                {
                    message = await _runnerServer.GetAgentMessageAsync(_settings.PoolId,
                                                                _session.SessionId,
                                                                _lastMessageId,
                                                                token);

                    // Decrypt the message body if the session is using encryption
                    message = DecryptMessage(message);

                    if (message != null)
                    {
                        _lastMessageId = message.MessageId;
                    }

                    if (encounteringError) //print the message once only if there was an error
                    {
                        _term.WriteLine($"{DateTime.UtcNow:u}: Runner reconnected.");
                        encounteringError = false;
                        continuousError = 0;
                    }
                }
                catch (OperationCanceledException) when (token.IsCancellationRequested)
                {
                    Trace.Info("Get next message has been cancelled.");
                    throw;
                }
                catch (TaskAgentAccessTokenExpiredException)
                {
                    Trace.Info("Runner OAuth token has been revoked. Unable to pull message.");
                    throw;
                }
                catch (Exception ex)
                {
                    Trace.Error("Catch exception during get next message.");
                    Trace.Error(ex);

                    // don't retry if SkipSessionRecover = true, DT service will delete agent session to stop agent from taking more jobs.
                    if (ex is TaskAgentSessionExpiredException && !_settings.SkipSessionRecover && await CreateSessionAsync(token))
                    {
                        Trace.Info($"{nameof(TaskAgentSessionExpiredException)} received, recovered by recreate session.");
                    }
                    else if (!IsGetNextMessageExceptionRetriable(ex))
                    {
                        throw;
                    }
                    else
                    {
                        continuousError++;
                        //retry after a random backoff to avoid service throttling
                        //in case of there is a service error happened and all agents get kicked off of the long poll and all agent try to reconnect back at the same time.
                        if (continuousError <= 5)
                        {
                            // random backoff [15, 30]
                            _getNextMessageRetryInterval = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(30), _getNextMessageRetryInterval);
                        }
                        else
                        {
                            // more aggressive backoff [30, 60]
                            _getNextMessageRetryInterval = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(60), _getNextMessageRetryInterval);
                        }

                        if (!encounteringError)
                        {
                            //print error only on the first consecutive error
                            _term.WriteError($"{DateTime.UtcNow:u}: Runner connect error: {ex.Message}. Retrying until reconnected.");
                            encounteringError = true;
                        }

                        // re-create VssConnection before next retry
                        await _runnerServer.RefreshConnectionAsync(RunnerConnectionType.MessageQueue, TimeSpan.FromSeconds(60));

                        Trace.Info("Sleeping for {0} seconds before retrying.", _getNextMessageRetryInterval.TotalSeconds);
                        await HostContext.Delay(_getNextMessageRetryInterval, token);
                    }
                }

                if (message == null)
                {
                    if (heartbeat.Elapsed > TimeSpan.FromMinutes(30))
                    {
                        Trace.Info($"No message retrieved from session '{_session.SessionId}' within last 30 minutes.");
                        heartbeat.Restart();
                    }
                    else
                    {
                        Trace.Verbose($"No message retrieved from session '{_session.SessionId}'.");
                    }

                    continue;
                }

                Trace.Info($"Message '{message.MessageId}' received from session '{_session.SessionId}'.");
                return message;
            }
        }

19 View Source File : GitSourceProvider.cs
License : MIT License
Project Creator : actions

public async Task GetSourceAsync(
            RunnerActionPluginExecutionContext executionContext,
            string repositoryPath,
            string repoFullName,
            string sourceBranch,
            string sourceVersion,
            bool clean,
            string submoduleInput,
            int fetchDepth,
            bool gitLfsSupport,
            string accessToken,
            CancellationToken cancellationToken)
        {
            // Validate args.
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            Dictionary<string, string> configModifications = new Dictionary<string, string>();
            executionContext.Output($"Syncing repository: {repoFullName}");
            Uri repositoryUrl = new Uri($"https://github.com/{repoFullName}");
            if (!repositoryUrl.IsAbsoluteUri)
            {
                throw new InvalidOperationException("Repository url need to be an absolute uri.");
            }

            string targetPath = repositoryPath;

            // input Submodules can be ['', true, false, recursive]
            // '' or false indicate don't checkout submodules
            // true indicate checkout top level submodules
            // recursive indicate checkout submodules recursively 
            bool checkoutSubmodules = false;
            bool checkoutNestedSubmodules = false;
            if (!string.IsNullOrEmpty(submoduleInput))
            {
                if (string.Equals(submoduleInput, Pipelines.PipelineConstants.CheckoutTaskInputs.SubmodulesOptions.Recursive, StringComparison.OrdinalIgnoreCase))
                {
                    checkoutSubmodules = true;
                    checkoutNestedSubmodules = true;
                }
                else
                {
                    checkoutSubmodules = StringUtil.ConvertToBoolean(submoduleInput);
                }
            }

            executionContext.Debug($"repository url={repositoryUrl}");
            executionContext.Debug($"targetPath={targetPath}");
            executionContext.Debug($"sourceBranch={sourceBranch}");
            executionContext.Debug($"sourceVersion={sourceVersion}");
            executionContext.Debug($"clean={clean}");
            executionContext.Debug($"checkoutSubmodules={checkoutSubmodules}");
            executionContext.Debug($"checkoutNestedSubmodules={checkoutNestedSubmodules}");
            executionContext.Debug($"fetchDepth={fetchDepth}");
            executionContext.Debug($"gitLfsSupport={gitLfsSupport}");

            // Initialize git command manager with additional environment variables.
            Dictionary<string, string> gitEnv = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

            // Disable git prompt
            gitEnv["GIT_TERMINAL_PROMPT"] = "0";

            // Disable prompting for git credential manager
            gitEnv["GCM_INTERACTIVE"] = "Never";

            // Git-lfs will try to pull down replacedet if any of the local/user/system setting exist.
            // If customer didn't enable `LFS` in their pipeline definition, we will use ENV to disable LFS fetch/checkout.
            if (!gitLfsSupport)
            {
                gitEnv["GIT_LFS_SKIP_SMUDGE"] = "1";
            }

            // Add the public variables.
            foreach (var variable in executionContext.Variables)
            {
                // Add the variable using the formatted name.
                string formattedKey = (variable.Key ?? string.Empty).Replace('.', '_').Replace(' ', '_').ToUpperInvariant();
                gitEnv[formattedKey] = variable.Value?.Value ?? string.Empty;
            }

            GitCliManager gitCommandManager = new GitCliManager(gitEnv);
            await gitCommandManager.LoadGitExecutionInfo(executionContext);

            // Make sure the build machine met all requirements for the git repository
            // For now, the requirement we have are:
            // 1. git version greater than 2.9 since we need to use auth header.
            // 2. git-lfs version greater than 2.1 since we need to use auth header.
            // 3. git version greater than 2.14.2 if use SChannel for SSL backend (Windows only)
            RequirementCheck(executionContext, gitCommandManager, gitLfsSupport);

            // prepare askpreplaced for client cert private key, if the repository's endpoint url match the runner config url
            var systemConnection = executionContext.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));

            // Check the current contents of the root folder to see if there is already a repo
            // If there is a repo, see if it matches the one we are expecting to be there based on the remote fetch url
            // if the repo is not what we expect, remove the folder
            if (!await IsRepositoryOriginUrlMatch(executionContext, gitCommandManager, targetPath, repositoryUrl))
            {
                // Delete source folder
                IOUtil.DeleteDirectory(targetPath, cancellationToken);
            }
            else
            {
                // delete the index.lock file left by previous canceled build or any operation cause git.exe crash last time.
                string lockFile = Path.Combine(targetPath, ".git\\index.lock");
                if (File.Exists(lockFile))
                {
                    try
                    {
                        File.Delete(lockFile);
                    }
                    catch (Exception ex)
                    {
                        executionContext.Debug($"Unable to delete the index.lock file: {lockFile}");
                        executionContext.Debug(ex.ToString());
                    }
                }

                // delete the shallow.lock file left by previous canceled build or any operation cause git.exe crash last time.		
                string shallowLockFile = Path.Combine(targetPath, ".git\\shallow.lock");
                if (File.Exists(shallowLockFile))
                {
                    try
                    {
                        File.Delete(shallowLockFile);
                    }
                    catch (Exception ex)
                    {
                        executionContext.Debug($"Unable to delete the shallow.lock file: {shallowLockFile}");
                        executionContext.Debug(ex.ToString());
                    }
                }

                // When repo.clean is selected for a git repo, execute git clean -ffdx and git reset --hard HEAD on the current repo.
                // This will help us save the time to reclone the entire repo.
                // If any git commands exit with non-zero return code or any exception happened during git.exe invoke, fall back to delete the repo folder.
                if (clean)
                {
                    Boolean softCleanSucceed = true;

                    // git clean -ffdx
                    int exitCode_clean = await gitCommandManager.GitClean(executionContext, targetPath);
                    if (exitCode_clean != 0)
                    {
                        executionContext.Debug($"'git clean -ffdx' failed with exit code {exitCode_clean}, this normally caused by:\n    1) Path too long\n    2) Permission issue\n    3) File in use\nFor futher investigation, manually run 'git clean -ffdx' on repo root: {targetPath} after each build.");
                        softCleanSucceed = false;
                    }

                    // git reset --hard HEAD
                    if (softCleanSucceed)
                    {
                        int exitCode_reset = await gitCommandManager.GitReset(executionContext, targetPath);
                        if (exitCode_reset != 0)
                        {
                            executionContext.Debug($"'git reset --hard HEAD' failed with exit code {exitCode_reset}\nFor futher investigation, manually run 'git reset --hard HEAD' on repo root: {targetPath} after each build.");
                            softCleanSucceed = false;
                        }
                    }

                    // git clean -ffdx and git reset --hard HEAD for each submodule
                    if (checkoutSubmodules)
                    {
                        if (softCleanSucceed)
                        {
                            int exitCode_submoduleclean = await gitCommandManager.GitSubmoduleClean(executionContext, targetPath);
                            if (exitCode_submoduleclean != 0)
                            {
                                executionContext.Debug($"'git submodule foreach git clean -ffdx' failed with exit code {exitCode_submoduleclean}\nFor futher investigation, manually run 'git submodule foreach git clean -ffdx' on repo root: {targetPath} after each build.");
                                softCleanSucceed = false;
                            }
                        }

                        if (softCleanSucceed)
                        {
                            int exitCode_submodulereset = await gitCommandManager.GitSubmoduleReset(executionContext, targetPath);
                            if (exitCode_submodulereset != 0)
                            {
                                executionContext.Debug($"'git submodule foreach git reset --hard HEAD' failed with exit code {exitCode_submodulereset}\nFor futher investigation, manually run 'git submodule foreach git reset --hard HEAD' on repo root: {targetPath} after each build.");
                                softCleanSucceed = false;
                            }
                        }
                    }

                    if (!softCleanSucceed)
                    {
                        //fall back
                        executionContext.Warning("Unable to run \"git clean -ffdx\" and \"git reset --hard HEAD\" successfully, delete source folder instead.");
                        IOUtil.DeleteDirectory(targetPath, cancellationToken);
                    }
                }
            }

            // if the folder is missing, create it
            if (!Directory.Exists(targetPath))
            {
                Directory.CreateDirectory(targetPath);
            }

            // if the folder contains a .git folder, it means the folder contains a git repo that matches the remote url and in a clean state.
            // we will run git fetch to update the repo.
            if (!Directory.Exists(Path.Combine(targetPath, ".git")))
            {
                // init git repository
                int exitCode_init = await gitCommandManager.GitInit(executionContext, targetPath);
                if (exitCode_init != 0)
                {
                    throw new InvalidOperationException($"Unable to use git.exe init repository under {targetPath}, 'git init' failed with exit code: {exitCode_init}");
                }

                int exitCode_addremote = await gitCommandManager.GitRemoteAdd(executionContext, targetPath, "origin", repositoryUrl.AbsoluteUri);
                if (exitCode_addremote != 0)
                {
                    throw new InvalidOperationException($"Unable to use git.exe add remote 'origin', 'git remote add' failed with exit code: {exitCode_addremote}");
                }
            }

            cancellationToken.ThrowIfCancellationRequested();

            // disable git auto gc
            int exitCode_disableGC = await gitCommandManager.GitDisableAutoGC(executionContext, targetPath);
            if (exitCode_disableGC != 0)
            {
                executionContext.Warning("Unable turn off git auto garbage collection, git fetch operation may trigger auto garbage collection which will affect the performance of fetching.");
            }

            // always remove any possible left extraheader setting from git config.
            if (await gitCommandManager.GitConfigExist(executionContext, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader"))
            {
                executionContext.Debug("Remove any extraheader setting from git config.");
                await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader", string.Empty);
            }

            List<string> additionalFetchArgs = new List<string>();
            List<string> additionalLfsFetchArgs = new List<string>();

            // Add http.https://github.com.extraheader=... to gitconfig
            // accessToken as basic auth header to handle any auth challenge from github.com 
            string configKey = $"http.https://github.com/.extraheader";
            string configValue = $"\"AUTHORIZATION: {GenerateBasicAuthHeader(executionContext, accessToken)}\"";
            configModifications[configKey] = configValue.Trim('\"');
            int exitCode_config = await gitCommandManager.GitConfig(executionContext, targetPath, configKey, configValue);
            if (exitCode_config != 0)
            {
                throw new InvalidOperationException($"Git config failed with exit code: {exitCode_config}");
            }

            // Prepare gitlfs url for fetch and checkout
            if (gitLfsSupport)
            {
                // Initialize git lfs by execute 'git lfs install'
                executionContext.Debug("Setup the local Git hooks for Git LFS.");
                int exitCode_lfsInstall = await gitCommandManager.GitLFSInstall(executionContext, targetPath);
                if (exitCode_lfsInstall != 0)
                {
                    throw new InvalidOperationException($"Git-lfs installation failed with exit code: {exitCode_lfsInstall}");
                }
            }

            List<string> additionalFetchSpecs = new List<string>();
            additionalFetchSpecs.Add("+refs/heads/*:refs/remotes/origin/*");

            if (IsPullRequest(sourceBranch))
            {
                additionalFetchSpecs.Add($"+{sourceBranch}:{GetRemoteRefName(sourceBranch)}");
            }

            int exitCode_fetch = await gitCommandManager.GitFetch(executionContext, targetPath, "origin", fetchDepth, additionalFetchSpecs, string.Join(" ", additionalFetchArgs), cancellationToken);
            if (exitCode_fetch != 0)
            {
                throw new InvalidOperationException($"Git fetch failed with exit code: {exitCode_fetch}");
            }

            // Checkout
            // sourceToBuild is used for checkout
            // if sourceBranch is a PR branch or sourceVersion is null, make sure branch name is a remote branch. we need checkout to detached head. 
            // (change refs/heads to refs/remotes/origin, refs/pull to refs/remotes/pull, or leave it as it when the branch name doesn't contain refs/...)
            // if sourceVersion provide, just use that for checkout, since when you checkout a commit, it will end up in detached head.
            cancellationToken.ThrowIfCancellationRequested();
            string sourcesToBuild;
            if (IsPullRequest(sourceBranch) || string.IsNullOrEmpty(sourceVersion))
            {
                sourcesToBuild = GetRemoteRefName(sourceBranch);
            }
            else
            {
                sourcesToBuild = sourceVersion;
            }

            // fetch lfs object upfront, this will avoid fetch lfs object during checkout which cause checkout taking forever
            // since checkout will fetch lfs object 1 at a time, while git lfs fetch will fetch lfs object in parallel.
            if (gitLfsSupport)
            {
                int exitCode_lfsFetch = await gitCommandManager.GitLFSFetch(executionContext, targetPath, "origin", sourcesToBuild, string.Join(" ", additionalLfsFetchArgs), cancellationToken);
                if (exitCode_lfsFetch != 0)
                {
                    // local repository is shallow repository, lfs fetch may fail due to lack of commits history.
                    // this will happen when the checkout commit is older than tip -> fetchDepth
                    if (fetchDepth > 0)
                    {
                        executionContext.Warning($"Git lfs fetch failed on shallow repository, this might because of git fetch with depth '{fetchDepth}' doesn't include the lfs fetch commit '{sourcesToBuild}'.");
                    }

                    // git lfs fetch failed, get lfs log, the log is critical for debug.
                    int exitCode_lfsLogs = await gitCommandManager.GitLFSLogs(executionContext, targetPath);
                    throw new InvalidOperationException($"Git lfs fetch failed with exit code: {exitCode_lfsFetch}. Git lfs logs returned with exit code: {exitCode_lfsLogs}.");
                }
            }

            // Finally, checkout the sourcesToBuild (if we didn't find a valid git object this will throw)
            int exitCode_checkout = await gitCommandManager.GitCheckout(executionContext, targetPath, sourcesToBuild, cancellationToken);
            if (exitCode_checkout != 0)
            {
                // local repository is shallow repository, checkout may fail due to lack of commits history.
                // this will happen when the checkout commit is older than tip -> fetchDepth
                if (fetchDepth > 0)
                {
                    executionContext.Warning($"Git checkout failed on shallow repository, this might because of git fetch with depth '{fetchDepth}' doesn't include the checkout commit '{sourcesToBuild}'.");
                }

                throw new InvalidOperationException($"Git checkout failed with exit code: {exitCode_checkout}");
            }

            // Submodule update
            if (checkoutSubmodules)
            {
                cancellationToken.ThrowIfCancellationRequested();

                int exitCode_submoduleSync = await gitCommandManager.GitSubmoduleSync(executionContext, targetPath, checkoutNestedSubmodules, cancellationToken);
                if (exitCode_submoduleSync != 0)
                {
                    throw new InvalidOperationException($"Git submodule sync failed with exit code: {exitCode_submoduleSync}");
                }

                List<string> additionalSubmoduleUpdateArgs = new List<string>();

                int exitCode_submoduleUpdate = await gitCommandManager.GitSubmoduleUpdate(executionContext, targetPath, fetchDepth, string.Join(" ", additionalSubmoduleUpdateArgs), checkoutNestedSubmodules, cancellationToken);
                if (exitCode_submoduleUpdate != 0)
                {
                    throw new InvalidOperationException($"Git submodule update failed with exit code: {exitCode_submoduleUpdate}");
                }
            }

            // Set intra-task variable for post job cleanup
            executionContext.SetIntraActionState("repositoryPath", targetPath);
            executionContext.SetIntraActionState("modifiedgitconfig", JsonUtility.ToString(configModifications.Keys));
            foreach (var config in configModifications)
            {
                executionContext.SetIntraActionState(config.Key, config.Value);
            }
        }

19 View Source File : IOUtil.cs
License : MIT License
Project Creator : actions

public static void CopyDirectory(string source, string target, CancellationToken cancellationToken)
        {
            // Validate args.
            ArgUtil.Directory(source, nameof(source));
            ArgUtil.NotNullOrEmpty(target, nameof(target));
            ArgUtil.NotNull(cancellationToken, nameof(cancellationToken));
            cancellationToken.ThrowIfCancellationRequested();

            // Create the target directory.
            Directory.CreateDirectory(target);

            // Get the file contents of the directory to copy.
            DirectoryInfo sourceDir = new DirectoryInfo(source);
            foreach (FileInfo sourceFile in sourceDir.GetFiles() ?? new FileInfo[0])
            {
                // Check if the file already exists.
                cancellationToken.ThrowIfCancellationRequested();
                FileInfo targetFile = new FileInfo(Path.Combine(target, sourceFile.Name));
                if (!targetFile.Exists ||
                    sourceFile.Length != targetFile.Length ||
                    sourceFile.LastWriteTime != targetFile.LastWriteTime)
                {
                    // Copy the file.
                    sourceFile.CopyTo(targetFile.FullName, true);
                }
            }

            // Copy the subdirectories.
            foreach (DirectoryInfo subDir in sourceDir.GetDirectories() ?? new DirectoryInfo[0])
            {
                CopyDirectory(
                    source: subDir.FullName,
                    target: Path.Combine(target, subDir.Name),
                    cancellationToken: cancellationToken);
            }
        }

19 View Source File : ProcessInvoker.cs
License : MIT License
Project Creator : actions

public async Task<int> ExecuteAsync(
            string workingDirectory,
            string fileName,
            string arguments,
            IDictionary<string, string> environment,
            bool requireExitCodeZero,
            Encoding outputEncoding,
            bool killProcessOnCancel,
            Channel<string> redirectStandardIn,
            bool inheritConsoleHandler,
            bool keepStandardInOpen,
            bool highPriorityProcess,
            CancellationToken cancellationToken)
        {
            ArgUtil.Null(_proc, nameof(_proc));
            ArgUtil.NotNullOrEmpty(fileName, nameof(fileName));

            Trace.Info("Starting process:");
            Trace.Info($"  File name: '{fileName}'");
            Trace.Info($"  Arguments: '{arguments}'");
            Trace.Info($"  Working directory: '{workingDirectory}'");
            Trace.Info($"  Require exit code zero: '{requireExitCodeZero}'");
            Trace.Info($"  Encoding web name: {outputEncoding?.WebName} ; code page: '{outputEncoding?.CodePage}'");
            Trace.Info($"  Force kill process on cancellation: '{killProcessOnCancel}'");
            Trace.Info($"  Redirected STDIN: '{redirectStandardIn != null}'");
            Trace.Info($"  Persist current code page: '{inheritConsoleHandler}'");
            Trace.Info($"  Keep redirected STDIN open: '{keepStandardInOpen}'");
            Trace.Info($"  High priority process: '{highPriorityProcess}'");

            _proc = new Process();
            _proc.StartInfo.FileName = fileName;
            _proc.StartInfo.Arguments = arguments;
            _proc.StartInfo.WorkingDirectory = workingDirectory;
            _proc.StartInfo.UseShellExecute = false;
            _proc.StartInfo.CreateNoWindow = !inheritConsoleHandler;
            _proc.StartInfo.RedirectStandardInput = true;
            _proc.StartInfo.RedirectStandardError = true;
            _proc.StartInfo.RedirectStandardOutput = true;

            // Ensure we process STDERR even the process exit event happen before we start read STDERR stream. 
            if (_proc.StartInfo.RedirectStandardError)
            {
                Interlocked.Increment(ref _asyncStreamReaderCount);
            }

            // Ensure we process STDOUT even the process exit event happen before we start read STDOUT stream.
            if (_proc.StartInfo.RedirectStandardOutput)
            {
                Interlocked.Increment(ref _asyncStreamReaderCount);
            }

#if OS_WINDOWS
            // If StandardErrorEncoding or StandardOutputEncoding is not specified the on the
            // ProcessStartInfo object, then .NET PInvokes to resolve the default console output
            // code page:
            //      [DllImport("api-ms-win-core-console-l1-1-0.dll", SetLastError = true)]
            //      public extern static uint GetConsoleOutputCP();
            StringUtil.EnsureRegisterEncodings();
#endif
            if (outputEncoding != null)
            {
                _proc.StartInfo.StandardErrorEncoding = outputEncoding;
                _proc.StartInfo.StandardOutputEncoding = outputEncoding;
            }

            // Copy the environment variables.
            if (environment != null && environment.Count > 0)
            {
                foreach (KeyValuePair<string, string> kvp in environment)
                {
                    _proc.StartInfo.Environment[kvp.Key] = kvp.Value;
                }
            }

            // Indicate GitHub Actions process.
            _proc.StartInfo.Environment["GITHUB_ACTIONS"] = "true";

            // Set CI=true when no one else already set it.
            // CI=true is common set in most CI provider in GitHub
            if (!_proc.StartInfo.Environment.ContainsKey("CI") &&
                Environment.GetEnvironmentVariable("CI") == null)
            {
                _proc.StartInfo.Environment["CI"] = "true";
            }

            // Hook up the events.
            _proc.EnableRaisingEvents = true;
            _proc.Exited += ProcessExitedHandler;

            // Start the process.
            _stopWatch = Stopwatch.StartNew();
            _proc.Start();

            // Decrease invoked process priority, in platform specifc way, relative to parent
            if (!highPriorityProcess)
            {
                DecreaseProcessPriority(_proc);
            }

            // Start the standard error notifications, if appropriate.
            if (_proc.StartInfo.RedirectStandardError)
            {
                StartReadStream(_proc.StandardError, _errorData);
            }

            // Start the standard output notifications, if appropriate.
            if (_proc.StartInfo.RedirectStandardOutput)
            {
                StartReadStream(_proc.StandardOutput, _outputData);
            }

            if (_proc.StartInfo.RedirectStandardInput)
            {
                if (redirectStandardIn != null)
                {
                    StartWriteStream(redirectStandardIn, _proc.StandardInput, keepStandardInOpen);
                }
                else
                {
                    // Close the input stream. This is done to prevent commands from blocking the build waiting for input from the user.
                    _proc.StandardInput.Close();
                }
            }

            var cancellationFinished = new TaskCompletionSource<bool>();
            using (var registration = cancellationToken.Register(async () =>
            {
                await CancelAndKillProcessTree(killProcessOnCancel);
                cancellationFinished.TrySetResult(true);
            }))
            {
                Trace.Info($"Process started with process id {_proc.Id}, waiting for process exit.");
                while (true)
                {
                    Task outputSignal = _outputProcessEvent.WaitAsync();
                    var signaled = await Task.WhenAny(outputSignal, _processExitedCompletionSource.Task);

                    if (signaled == outputSignal)
                    {
                        ProcessOutput();
                    }
                    else
                    {
                        _stopWatch.Stop();
                        break;
                    }
                }

                // Just in case there was some pending output when the process shut down go ahead and check the
                // data buffers one last time before returning
                ProcessOutput();

                if (cancellationToken.IsCancellationRequested)
                {
                    // Ensure cancellation also finish on the cancellationToken.Register thread.
                    await cancellationFinished.Task;
                    Trace.Info($"Process Cancellation finished.");
                }

                Trace.Info($"Finished process {_proc.Id} with exit code {_proc.ExitCode}, and elapsed time {_stopWatch.Elapsed}.");
            }

            cancellationToken.ThrowIfCancellationRequested();

            // Wait for process to finish.
            if (_proc.ExitCode != 0 && requireExitCodeZero)
            {
                throw new ProcessExitCodeException(exitCode: _proc.ExitCode, fileName: fileName, arguments: arguments);
            }

            return _proc.ExitCode;
        }

19 View Source File : GitSourceProvider.cs
License : MIT License
Project Creator : actions

public async Task GetSourceAsync(
            RunnerActionPluginExecutionContext executionContext,
            string repositoryPath,
            string repoFullName,
            string sourceBranch,
            string sourceVersion,
            bool clean,
            string submoduleInput,
            int fetchDepth,
            bool gitLfsSupport,
            string accessToken,
            CancellationToken cancellationToken)
        {
            // Validate args.
            ArgUtil.NotNull(executionContext, nameof(executionContext));
            executionContext.Output($"Syncing repository: {repoFullName}");

            // Repository URL
            var githubUrl = executionContext.GetGitHubContext("server_url");
            var githubUri = new Uri(!string.IsNullOrEmpty(githubUrl) ? githubUrl : "https://github.com");
            var portInfo = githubUri.IsDefaultPort ? string.Empty : $":{githubUri.Port}";
            Uri repositoryUrl = new Uri($"{githubUri.Scheme}://{githubUri.Host}{portInfo}/{repoFullName}");
            if (!repositoryUrl.IsAbsoluteUri)
            {
                throw new InvalidOperationException("Repository url need to be an absolute uri.");
            }

            string targetPath = repositoryPath;

            // input Submodules can be ['', true, false, recursive]
            // '' or false indicate don't checkout submodules
            // true indicate checkout top level submodules
            // recursive indicate checkout submodules recursively 
            bool checkoutSubmodules = false;
            bool checkoutNestedSubmodules = false;
            if (!string.IsNullOrEmpty(submoduleInput))
            {
                if (string.Equals(submoduleInput, Pipelines.PipelineConstants.CheckoutTaskInputs.SubmodulesOptions.Recursive, StringComparison.OrdinalIgnoreCase))
                {
                    checkoutSubmodules = true;
                    checkoutNestedSubmodules = true;
                }
                else
                {
                    checkoutSubmodules = StringUtil.ConvertToBoolean(submoduleInput);
                }
            }

            executionContext.Debug($"repository url={repositoryUrl}");
            executionContext.Debug($"targetPath={targetPath}");
            executionContext.Debug($"sourceBranch={sourceBranch}");
            executionContext.Debug($"sourceVersion={sourceVersion}");
            executionContext.Debug($"clean={clean}");
            executionContext.Debug($"checkoutSubmodules={checkoutSubmodules}");
            executionContext.Debug($"checkoutNestedSubmodules={checkoutNestedSubmodules}");
            executionContext.Debug($"fetchDepth={fetchDepth}");
            executionContext.Debug($"gitLfsSupport={gitLfsSupport}");

            // Initialize git command manager with additional environment variables.
            Dictionary<string, string> gitEnv = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

            // Disable prompting for git credential manager
            gitEnv["GCM_INTERACTIVE"] = "Never";

            // Git-lfs will try to pull down replacedet if any of the local/user/system setting exist.
            // If customer didn't enable `LFS` in their pipeline definition, we will use ENV to disable LFS fetch/checkout.
            if (!gitLfsSupport)
            {
                gitEnv["GIT_LFS_SKIP_SMUDGE"] = "1";
            }

            // Add the public variables.
            foreach (var variable in executionContext.Variables)
            {
                // Add the variable using the formatted name.
                string formattedKey = (variable.Key ?? string.Empty).Replace('.', '_').Replace(' ', '_').ToUpperInvariant();
                gitEnv[formattedKey] = variable.Value?.Value ?? string.Empty;
            }

            GitCliManager gitCommandManager = new GitCliManager(gitEnv);
            await gitCommandManager.LoadGitExecutionInfo(executionContext);

            // Make sure the build machine met all requirements for the git repository
            // For now, the requirement we have are:
            // 1. git version greater than 2.9 since we need to use auth header.
            // 2. git-lfs version greater than 2.1 since we need to use auth header.
            // 3. git version greater than 2.14.2 if use SChannel for SSL backend (Windows only)
            RequirementCheck(executionContext, gitCommandManager, gitLfsSupport);

            // prepare askpreplaced for client cert private key, if the repository's endpoint url match the runner config url
            var systemConnection = executionContext.Endpoints.Single(x => string.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));

            // Check the current contents of the root folder to see if there is already a repo
            // If there is a repo, see if it matches the one we are expecting to be there based on the remote fetch url
            // if the repo is not what we expect, remove the folder
            if (!await IsRepositoryOriginUrlMatch(executionContext, gitCommandManager, targetPath, repositoryUrl))
            {
                // Delete source folder
                IOUtil.DeleteDirectory(targetPath, cancellationToken);
            }
            else
            {
                // delete the index.lock file left by previous canceled build or any operation cause git.exe crash last time.
                string lockFile = Path.Combine(targetPath, ".git\\index.lock");
                if (File.Exists(lockFile))
                {
                    try
                    {
                        File.Delete(lockFile);
                    }
                    catch (Exception ex)
                    {
                        executionContext.Debug($"Unable to delete the index.lock file: {lockFile}");
                        executionContext.Debug(ex.ToString());
                    }
                }

                // delete the shallow.lock file left by previous canceled build or any operation cause git.exe crash last time.		
                string shallowLockFile = Path.Combine(targetPath, ".git\\shallow.lock");
                if (File.Exists(shallowLockFile))
                {
                    try
                    {
                        File.Delete(shallowLockFile);
                    }
                    catch (Exception ex)
                    {
                        executionContext.Debug($"Unable to delete the shallow.lock file: {shallowLockFile}");
                        executionContext.Debug(ex.ToString());
                    }
                }

                // When repo.clean is selected for a git repo, execute git clean -ffdx and git reset --hard HEAD on the current repo.
                // This will help us save the time to reclone the entire repo.
                // If any git commands exit with non-zero return code or any exception happened during git.exe invoke, fall back to delete the repo folder.
                if (clean)
                {
                    Boolean softCleanSucceed = true;

                    // git clean -ffdx
                    int exitCode_clean = await gitCommandManager.GitClean(executionContext, targetPath);
                    if (exitCode_clean != 0)
                    {
                        executionContext.Debug($"'git clean -ffdx' failed with exit code {exitCode_clean}, this normally caused by:\n    1) Path too long\n    2) Permission issue\n    3) File in use\nFor futher investigation, manually run 'git clean -ffdx' on repo root: {targetPath} after each build.");
                        softCleanSucceed = false;
                    }

                    // git reset --hard HEAD
                    if (softCleanSucceed)
                    {
                        int exitCode_reset = await gitCommandManager.GitReset(executionContext, targetPath);
                        if (exitCode_reset != 0)
                        {
                            executionContext.Debug($"'git reset --hard HEAD' failed with exit code {exitCode_reset}\nFor futher investigation, manually run 'git reset --hard HEAD' on repo root: {targetPath} after each build.");
                            softCleanSucceed = false;
                        }
                    }

                    // git clean -ffdx and git reset --hard HEAD for each submodule
                    if (checkoutSubmodules)
                    {
                        if (softCleanSucceed)
                        {
                            int exitCode_submoduleclean = await gitCommandManager.GitSubmoduleClean(executionContext, targetPath);
                            if (exitCode_submoduleclean != 0)
                            {
                                executionContext.Debug($"'git submodule foreach git clean -ffdx' failed with exit code {exitCode_submoduleclean}\nFor futher investigation, manually run 'git submodule foreach git clean -ffdx' on repo root: {targetPath} after each build.");
                                softCleanSucceed = false;
                            }
                        }

                        if (softCleanSucceed)
                        {
                            int exitCode_submodulereset = await gitCommandManager.GitSubmoduleReset(executionContext, targetPath);
                            if (exitCode_submodulereset != 0)
                            {
                                executionContext.Debug($"'git submodule foreach git reset --hard HEAD' failed with exit code {exitCode_submodulereset}\nFor futher investigation, manually run 'git submodule foreach git reset --hard HEAD' on repo root: {targetPath} after each build.");
                                softCleanSucceed = false;
                            }
                        }
                    }

                    if (!softCleanSucceed)
                    {
                        //fall back
                        executionContext.Warning("Unable to run \"git clean -ffdx\" and \"git reset --hard HEAD\" successfully, delete source folder instead.");
                        IOUtil.DeleteDirectory(targetPath, cancellationToken);
                    }
                }
            }

            // if the folder is missing, create it
            if (!Directory.Exists(targetPath))
            {
                Directory.CreateDirectory(targetPath);
            }

            // if the folder contains a .git folder, it means the folder contains a git repo that matches the remote url and in a clean state.
            // we will run git fetch to update the repo.
            if (!Directory.Exists(Path.Combine(targetPath, ".git")))
            {
                // init git repository
                int exitCode_init = await gitCommandManager.GitInit(executionContext, targetPath);
                if (exitCode_init != 0)
                {
                    throw new InvalidOperationException($"Unable to use git.exe init repository under {targetPath}, 'git init' failed with exit code: {exitCode_init}");
                }

                int exitCode_addremote = await gitCommandManager.GitRemoteAdd(executionContext, targetPath, "origin", repositoryUrl.AbsoluteUri);
                if (exitCode_addremote != 0)
                {
                    throw new InvalidOperationException($"Unable to use git.exe add remote 'origin', 'git remote add' failed with exit code: {exitCode_addremote}");
                }
            }

            cancellationToken.ThrowIfCancellationRequested();

            // disable git auto gc
            int exitCode_disableGC = await gitCommandManager.GitDisableAutoGC(executionContext, targetPath);
            if (exitCode_disableGC != 0)
            {
                executionContext.Warning("Unable turn off git auto garbage collection, git fetch operation may trigger auto garbage collection which will affect the performance of fetching.");
            }

            // always remove any possible left extraheader setting from git config.
            if (await gitCommandManager.GitConfigExist(executionContext, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader"))
            {
                executionContext.Debug("Remove any extraheader setting from git config.");
                await RemoveGitConfig(executionContext, gitCommandManager, targetPath, $"http.{repositoryUrl.AbsoluteUri}.extraheader", string.Empty);
            }

            List<string> additionalFetchArgs = new List<string>();
            List<string> additionalLfsFetchArgs = new List<string>();

            // add accessToken as basic auth header to handle auth challenge. 
            if (!string.IsNullOrEmpty(accessToken))
            {
                additionalFetchArgs.Add($"-c http.extraheader=\"AUTHORIZATION: {GenerateBasicAuthHeader(executionContext, accessToken)}\"");
            }

            // Prepare gitlfs url for fetch and checkout
            if (gitLfsSupport)
            {
                // Initialize git lfs by execute 'git lfs install'
                executionContext.Debug("Setup the local Git hooks for Git LFS.");
                int exitCode_lfsInstall = await gitCommandManager.GitLFSInstall(executionContext, targetPath);
                if (exitCode_lfsInstall != 0)
                {
                    throw new InvalidOperationException($"Git-lfs installation failed with exit code: {exitCode_lfsInstall}");
                }

                if (!string.IsNullOrEmpty(accessToken))
                {
                    string authorityUrl = repositoryUrl.AbsoluteUri.Replace(repositoryUrl.PathAndQuery, string.Empty);
                    additionalLfsFetchArgs.Add($"-c http.{authorityUrl}.extraheader=\"AUTHORIZATION: {GenerateBasicAuthHeader(executionContext, accessToken)}\"");
                }
            }

            List<string> additionalFetchSpecs = new List<string>();
            additionalFetchSpecs.Add("+refs/heads/*:refs/remotes/origin/*");

            if (IsPullRequest(sourceBranch))
            {
                additionalFetchSpecs.Add($"+{sourceBranch}:{GetRemoteRefName(sourceBranch)}");
            }

            int exitCode_fetch = await gitCommandManager.GitFetch(executionContext, targetPath, "origin", fetchDepth, additionalFetchSpecs, string.Join(" ", additionalFetchArgs), cancellationToken);
            if (exitCode_fetch != 0)
            {
                throw new InvalidOperationException($"Git fetch failed with exit code: {exitCode_fetch}");
            }

            // Checkout
            // sourceToBuild is used for checkout
            // if sourceBranch is a PR branch or sourceVersion is null, make sure branch name is a remote branch. we need checkout to detached head. 
            // (change refs/heads to refs/remotes/origin, refs/pull to refs/remotes/pull, or leave it as it when the branch name doesn't contain refs/...)
            // if sourceVersion provide, just use that for checkout, since when you checkout a commit, it will end up in detached head.
            cancellationToken.ThrowIfCancellationRequested();
            string sourcesToBuild;
            if (IsPullRequest(sourceBranch) || string.IsNullOrEmpty(sourceVersion))
            {
                sourcesToBuild = GetRemoteRefName(sourceBranch);
            }
            else
            {
                sourcesToBuild = sourceVersion;
            }

            // fetch lfs object upfront, this will avoid fetch lfs object during checkout which cause checkout taking forever
            // since checkout will fetch lfs object 1 at a time, while git lfs fetch will fetch lfs object in parallel.
            if (gitLfsSupport)
            {
                int exitCode_lfsFetch = await gitCommandManager.GitLFSFetch(executionContext, targetPath, "origin", sourcesToBuild, string.Join(" ", additionalLfsFetchArgs), cancellationToken);
                if (exitCode_lfsFetch != 0)
                {
                    // local repository is shallow repository, lfs fetch may fail due to lack of commits history.
                    // this will happen when the checkout commit is older than tip -> fetchDepth
                    if (fetchDepth > 0)
                    {
                        executionContext.Warning($"Git lfs fetch failed on shallow repository, this might because of git fetch with depth '{fetchDepth}' doesn't include the lfs fetch commit '{sourcesToBuild}'.");
                    }

                    // git lfs fetch failed, get lfs log, the log is critical for debug.
                    int exitCode_lfsLogs = await gitCommandManager.GitLFSLogs(executionContext, targetPath);
                    throw new InvalidOperationException($"Git lfs fetch failed with exit code: {exitCode_lfsFetch}. Git lfs logs returned with exit code: {exitCode_lfsLogs}.");
                }
            }

            // Finally, checkout the sourcesToBuild (if we didn't find a valid git object this will throw)
            int exitCode_checkout = await gitCommandManager.GitCheckout(executionContext, targetPath, sourcesToBuild, cancellationToken);
            if (exitCode_checkout != 0)
            {
                // local repository is shallow repository, checkout may fail due to lack of commits history.
                // this will happen when the checkout commit is older than tip -> fetchDepth
                if (fetchDepth > 0)
                {
                    executionContext.Warning($"Git checkout failed on shallow repository, this might because of git fetch with depth '{fetchDepth}' doesn't include the checkout commit '{sourcesToBuild}'.");
                }

                throw new InvalidOperationException($"Git checkout failed with exit code: {exitCode_checkout}");
            }

            // Submodule update
            if (checkoutSubmodules)
            {
                cancellationToken.ThrowIfCancellationRequested();

                int exitCode_submoduleSync = await gitCommandManager.GitSubmoduleSync(executionContext, targetPath, checkoutNestedSubmodules, cancellationToken);
                if (exitCode_submoduleSync != 0)
                {
                    throw new InvalidOperationException($"Git submodule sync failed with exit code: {exitCode_submoduleSync}");
                }

                List<string> additionalSubmoduleUpdateArgs = new List<string>();

                if (!string.IsNullOrEmpty(accessToken))
                {
                    string authorityUrl = repositoryUrl.AbsoluteUri.Replace(repositoryUrl.PathAndQuery, string.Empty);
                    additionalSubmoduleUpdateArgs.Add($"-c http.{authorityUrl}.extraheader=\"AUTHORIZATION: {GenerateBasicAuthHeader(executionContext, accessToken)}\"");
                }

                int exitCode_submoduleUpdate = await gitCommandManager.GitSubmoduleUpdate(executionContext, targetPath, fetchDepth, string.Join(" ", additionalSubmoduleUpdateArgs), checkoutNestedSubmodules, cancellationToken);
                if (exitCode_submoduleUpdate != 0)
                {
                    throw new InvalidOperationException($"Git submodule update failed with exit code: {exitCode_submoduleUpdate}");
                }
            }
        }

19 View Source File : IOUtil.cs
License : MIT License
Project Creator : actions

public static void DeleteDirectory(string path, bool contentsOnly, bool continueOnContentDeleteError, CancellationToken cancellationToken)
        {
            ArgUtil.NotNullOrEmpty(path, nameof(path));
            DirectoryInfo directory = new DirectoryInfo(path);
            if (!directory.Exists)
            {
                return;
            }

            if (!contentsOnly)
            {
                // Remove the readonly flag.
                RemoveReadOnly(directory);

                // Check if the directory is a reparse point.
                if (directory.Attributes.HasFlag(FileAttributes.ReparsePoint))
                {
                    // Delete the reparse point directory and short-circuit.
                    directory.Delete();
                    return;
                }
            }

            // Initialize a concurrent stack to store the directories. The directories
            // cannot be deleted until the files are deleted.
            var directories = new ConcurrentStack<DirectoryInfo>();

            if (!contentsOnly)
            {
                directories.Push(directory);
            }

            // Create a new token source for the parallel query. The parallel query should be
            // canceled after the first error is encountered. Otherwise the number of exceptions
            // could get out of control for a large directory with access denied on every file.
            using (var tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
            {
                try
                {
                    // Recursively delete all files and store all subdirectories.
                    Enumerate(directory, tokenSource)
                        .AsParallel()
                        .WithCancellation(tokenSource.Token)
                        .ForAll((FileSystemInfo item) =>
                        {
                            bool success = false;
                            try
                            {
                                // Remove the readonly attribute.
                                RemoveReadOnly(item);

                                // Check if the item is a file.
                                if (item is FileInfo)
                                {
                                    // Delete the file.
                                    item.Delete();
                                }
                                else
                                {
                                    // Check if the item is a directory reparse point.
                                    var subdirectory = item as DirectoryInfo;
                                    ArgUtil.NotNull(subdirectory, nameof(subdirectory));
                                    if (subdirectory.Attributes.HasFlag(FileAttributes.ReparsePoint))
                                    {
                                        try
                                        {
                                            // Delete the reparse point.
                                            subdirectory.Delete();
                                        }
                                        catch (DirectoryNotFoundException)
                                        {
                                            // The target of the reparse point directory has been deleted.
                                            // Therefore the item is no longer a directory and is now a file.
                                            //
                                            // Deletion of reparse point directories happens in parallel. This case can occur
                                            // when reparse point directory FOO points to some other reparse point directory BAR,
                                            // and BAR is deleted after the DirectoryInfo for FOO has already been initialized.
                                            File.Delete(subdirectory.FullName);
                                        }
                                    }
                                    else
                                    {
                                        // Store the directory.
                                        directories.Push(subdirectory);
                                    }
                                }

                                success = true;
                            }
                            catch (Exception) when (continueOnContentDeleteError)
                            {
                                // ignore any exception when continueOnContentDeleteError is true.
                                success = true;
                            }
                            finally
                            {
                                if (!success)
                                {
                                    tokenSource.Cancel(); // Cancel is thread-safe.
                                }
                            }
                        });
                }
                catch (Exception)
                {
                    tokenSource.Cancel();
                    throw;
                }
            }

            // Delete the directories.
            foreach (DirectoryInfo dir in directories.OrderByDescending(x => x.FullName.Length))
            {
                cancellationToken.ThrowIfCancellationRequested();
                dir.Delete();
            }
        }

19 View Source File : FileContainerHttpClient.cs
License : MIT License
Project Creator : actions

[EditorBrowsable(EditorBrowsableState.Never)]
        public async Task<HttpResponseMessage> UploadFileAsync(
            Int64 containerId,
            String itemPath,
            Stream fileStream,
            byte[] contentId,
            Int64 fileLength,
            Boolean isGzipped,
            Guid scopeIdentifier,
            CancellationToken cancellationToken = default(CancellationToken),
            int chunkSize = c_defaultChunkSize,
            int chunkRetryTimes = c_defaultChunkRetryTimes,
            bool uploadFirstChunk = false,
            Object userState = null)
        {
            if (containerId < 1)
            {
                throw new ArgumentException(WebApiResources.ContainerIdMustBeGreaterThanZero(), "containerId");
            }

            if (chunkSize > c_maxChunkSize)
            {
                chunkSize = c_maxChunkSize;
            }

            // if a contentId is specified but the chunk size is not a 2mb multiple error
            if (contentId != null && (chunkSize % c_ContentChunkMultiple) != 0)
            {
                throw new ArgumentException(FileContainerResources.ChunksizeWrongWithContentId(c_ContentChunkMultiple), "chunkSize");
            }

            ArgumentUtility.CheckForNull(fileStream, "fileStream");

            ApiResourceVersion gzipSupportedVersion = new ApiResourceVersion(new Version(1, 0), 2);
            ApiResourceVersion requestVersion = await NegotiateRequestVersionAsync(FileContainerResourceIds.FileContainer, s_currentApiVersion, userState, cancellationToken).ConfigureAwait(false);

            if (isGzipped
                && (requestVersion.ApiVersion < gzipSupportedVersion.ApiVersion
                    || (requestVersion.ApiVersion == gzipSupportedVersion.ApiVersion && requestVersion.ResourceVersion < gzipSupportedVersion.ResourceVersion)))
            {
                throw new ArgumentException(FileContainerResources.GzipNotSupportedOnServer(), "isGzipped");
            }

            if (isGzipped && fileStream.Length >= fileLength)
            {
                throw new ArgumentException(FileContainerResources.BadCompression(), "fileLength");
            }

            HttpRequestMessage requestMessage = null;
            List<KeyValuePair<String, String>> query = AppendItemQueryString(itemPath, scopeIdentifier);

            if (fileStream.Length == 0)
            {
                // zero byte upload
                FileUploadTrace(itemPath, $"Upload zero byte file '{itemPath}'.");
                requestMessage = await CreateRequestMessageAsync(HttpMethod.Put, FileContainerResourceIds.FileContainer, routeValues: new { containerId = containerId }, version: s_currentApiVersion, queryParameters: query, userState: userState, cancellationToken: cancellationToken).ConfigureAwait(false);
                return await SendAsync(requestMessage, userState, cancellationToken).ConfigureAwait(false);
            }

            bool multiChunk = false;
            int totalChunks = 1;
            if (fileStream.Length > chunkSize)
            {
                totalChunks = (int)Math.Ceiling(fileStream.Length / (double)chunkSize);
                FileUploadTrace(itemPath, $"Begin chunking upload file '{itemPath}', chunk size '{chunkSize} Bytes', total chunks '{totalChunks}'.");
                multiChunk = true;
            }
            else
            {
                FileUploadTrace(itemPath, $"File '{itemPath}' will be uploaded in one chunk.");
                chunkSize = (int)fileStream.Length;
            }

            StreamParser streamParser = new StreamParser(fileStream, chunkSize);
            SubStream currentStream = streamParser.GetNextStream();
            HttpResponseMessage response = null;

            Byte[] dataToSend = new Byte[chunkSize];
            int currentChunk = 0;
            Stopwatch uploadTimer = new Stopwatch();
            while (currentStream.Length > 0 && !cancellationToken.IsCancellationRequested)
            {
                currentChunk++;

                for (int attempt = 1; attempt <= chunkRetryTimes && !cancellationToken.IsCancellationRequested; attempt++)
                {
                    if (attempt > 1)
                    {
                        TimeSpan backoff = BackoffTimerHelper.GetRandomBackoff(TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(10));
                        FileUploadTrace(itemPath, $"Backoff {backoff.TotalSeconds} seconds before attempt '{attempt}' chunk '{currentChunk}' of file '{itemPath}'.");
                        await Task.Delay(backoff, cancellationToken).ConfigureAwait(false);
                        currentStream.Seek(0, SeekOrigin.Begin);
                    }

                    FileUploadTrace(itemPath, $"Attempt '{attempt}' for uploading chunk '{currentChunk}' of file '{itemPath}'.");

                    // inorder for the upload to be retryable, we need the content to be re-readable
                    // to ensure this we copy the chunk into a byte array and send that
                    // chunk size ensures we can convert the length to an int
                    int bytesToCopy = (int)currentStream.Length;
                    using (MemoryStream ms = new MemoryStream(dataToSend))
                    {
                        await currentStream.CopyToAsync(ms, bytesToCopy, cancellationToken).ConfigureAwait(false);
                    }

                    // set the content and the Content-Range header
                    HttpContent byteArrayContent = new ByteArrayContent(dataToSend, 0, bytesToCopy);
                    byteArrayContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
                    byteArrayContent.Headers.ContentLength = currentStream.Length;
                    byteArrayContent.Headers.ContentRange = new System.Net.Http.Headers.ContentRangeHeaderValue(currentStream.StartingPostionOnOuterStream,
                                                                                                             currentStream.EndingPostionOnOuterStream,
                                                                                                             streamParser.Length);
                    FileUploadTrace(itemPath, $"Generate new HttpRequest for uploading file '{itemPath}', chunk '{currentChunk}' of '{totalChunks}'.");

                    try
                    {
                        if (requestMessage != null)
                        {
                            requestMessage.Dispose();
                            requestMessage = null;
                        }

                        requestMessage = await CreateRequestMessageAsync(
                            HttpMethod.Put,
                            FileContainerResourceIds.FileContainer,
                            routeValues: new { containerId = containerId },
                            version: s_currentApiVersion,
                            content: byteArrayContent,
                            queryParameters: query,
                            userState: userState,
                            cancellationToken: cancellationToken).ConfigureAwait(false);
                    }
                    catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
                    {
                        // stop re-try on cancellation.
                        throw;
                    }
                    catch (Exception ex) when (attempt < chunkRetryTimes) // not the last attempt
                    {
                        FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' fail to create HttpRequest. Error: {ex.ToString()}.");
                        continue;
                    }

                    if (isGzipped)
                    {
                        //add gzip header info
                        byteArrayContent.Headers.ContentEncoding.Add("gzip");
                        byteArrayContent.Headers.Add("x-tfs-filelength", fileLength.ToString(System.Globalization.CultureInfo.InvariantCulture));
                    }

                    if (contentId != null)
                    {
                        byteArrayContent.Headers.Add("x-vso-contentId", Convert.ToBase64String(contentId)); // Base64FormattingOptions.None is default when not supplied
                    }

                    FileUploadTrace(itemPath, $"Start uploading file '{itemPath}' to server, chunk '{currentChunk}'.");
                    uploadTimer.Restart();

                    try
                    {
                        if (response != null)
                        {
                            response.Dispose();
                            response = null;
                        }

                        response = await SendAsync(requestMessage, userState, cancellationToken).ConfigureAwait(false);
                    }
                    catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
                    {
                        // stop re-try on cancellation.
                        throw;
                    }
                    catch (Exception ex) when (attempt < chunkRetryTimes) // not the last attempt
                    {
                        FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' fail to send request to server. Error: {ex.ToString()}.");
                        continue;
                    }

                    uploadTimer.Stop();
                    FileUploadTrace(itemPath, $"Finished upload chunk '{currentChunk}' of file '{itemPath}', elapsed {uploadTimer.ElapsedMilliseconds} (ms), response code '{response.StatusCode}'.");

                    if (multiChunk)
                    {
                        FileUploadProgress(itemPath, currentChunk, (int)Math.Ceiling(fileStream.Length / (double)chunkSize));
                    }

                    if (response.IsSuccessStatusCode)
                    {
                        break;
                    }
                    else if (IsFastFailResponse(response))
                    {
                        FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' received non-success status code {response.StatusCode} for sending request and cannot continue.");
                        break;
                    }
                    else
                    {
                        FileUploadTrace(itemPath, $"Chunk '{currentChunk}' attempt '{attempt}' of file '{itemPath}' received non-success status code {response.StatusCode} for sending request.");
                        continue;
                    }
                }

                // if we don't have success then bail and return the failed response
                if (!response.IsSuccessStatusCode)
                {
                    break;
                }

                if (contentId != null && response.StatusCode == HttpStatusCode.Created)
                {
                    // no need to keep uploading since the server said it has all the content
                    FileUploadTrace(itemPath, $"Stop chunking upload the rest of the file '{itemPath}', since server already has all the content.");
                    break;
                }

                currentStream = streamParser.GetNextStream();
                if (uploadFirstChunk)
                {
                    break;
                }
            }

            cancellationToken.ThrowIfCancellationRequested();

            return response;
        }

19 View Source File : ActionHandlerAttributesFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica

private async Task<Doreplacedent> FixActionHandlerAttributes(Doreplacedent doreplacedent, TextSpan span, FixOption option, CancellationToken cancellation)
        {
			cancellation.ThrowIfCancellationRequested();

            var root = await doreplacedent
                .GetSyntaxRootAsync(cancellation)
                .ConfigureAwait(false);

            if (!(root?.FindNode(span) is MethodDeclarationSyntax node))
            {
                return doreplacedent;
            }

            var semanticModel = await doreplacedent
                .GetSemanticModelAsync(cancellation)
                .ConfigureAwait(false);

            if (semanticModel == null)
            {
                return doreplacedent;
            }

            var pxContext = new PXContext(semanticModel.Compilation, codereplacedysisSettings: null);
			var pxButtonAttributeList = pxContext.AttributeTypes.PXButtonAttribute.GetAttributeList();
			var pxUIFieldAttributeList = pxContext.AttributeTypes.PXUIFieldAttribute.Type.GetAttributeList();
            var attributeListCollection = new List<AttributeListSyntax>();

            switch (option)
            {
                case FixOption.AddPXButtonAttribute:
					attributeListCollection.Add(pxButtonAttributeList);
                    break;
                case FixOption.AddPXUIFieldAttribute:
					attributeListCollection.Add(pxUIFieldAttributeList);
                    break;
                case FixOption.AddBothAttributes:
					attributeListCollection.Add(pxButtonAttributeList);
					attributeListCollection.Add(pxUIFieldAttributeList);
                    break;
            }

            var newNode = node.AddAttributeLists(attributeListCollection.ToArray());
            var newRoot = root.ReplaceNode(node, newNode);
            var newDoreplacedent = doreplacedent.WithSyntaxRoot(newRoot);

            return newDoreplacedent;
        }

19 View Source File : InternalApiCallsWalker.cs
License : GNU General Public License v3.0
Project Creator : Acumatica

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);
		}

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;
			}

public bool IsAttributeToRemove(AttributeSyntax attributeNode)
			{
				if (attributeNode.Equals(_remainingAttribute))
					return false;

				ITypeSymbol attributeType = _semanticModel.GetTypeInfo(attributeNode, _cancellationToken).Type;
				_cancellationToken.ThrowIfCancellationRequested();

				if (attributeType == null)
					return false;
				
				var attributeInfos = _attributesRegister.GetFieldTypeAttributeInfos(attributeType);
				return attributeInfos.Any(_attributeToRemovePredicate);
			}

19 View Source File : MultipleKeysInDacFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica

private async Task<Doreplacedent> DeleteOtherPrimaryKeyDeclarationsFromDacAsync(Doreplacedent doreplacedent, IReadOnlyList<Location> locationsToRemove,
																				   CancellationToken cancellation)
		{
			cancellation.ThrowIfCancellationRequested();

			SyntaxNode root = await doreplacedent.GetSyntaxRootAsync(cancellation).ConfigureAwait(false);

			if (root == null)
				return doreplacedent;

			var nodesToRemove = locationsToRemove.Select(location => root.FindNode(location.SourceSpan))
												 .OfType<ClreplacedDeclarationSyntax>();

			var newRoot = root.RemoveNodes(nodesToRemove, SyntaxRemoveOptions.KeepNoTrivia | SyntaxRemoveOptions.KeepUnbalancedDirectives);
			var newDoreplacedent = doreplacedent.WithSyntaxRoot(newRoot);

			cancellation.ThrowIfCancellationRequested();
			return newDoreplacedent;			
		}

19 View Source File : LocalizationMessageHelper.cs
License : GNU General Public License v3.0
Project Creator : Acumatica

private bool IsStringConcatenation()
        {
            Cancellation.ThrowIfCancellationRequested();

            bool isStringAddition = _messageExpression is BinaryExpressionSyntax && _messageExpression.IsKind(SyntaxKind.AddExpression);
            if (isStringAddition)
                return true;

            if (!(_messageExpression is InvocationExpressionSyntax i) || !(i.Expression is MemberAccessExpressionSyntax memberAccess) ||
                memberAccess.Expression == null || memberAccess.Name == null)
                return false;

            ITypeSymbol stringType = SemanticModel.GetTypeInfo(memberAccess.Expression, Cancellation).Type;
            if (stringType == null || stringType.SpecialType != SpecialType.System_String)
                return false;

            ISymbol stringMethod = SemanticModel.GetSymbolInfo(memberAccess.Name, Cancellation).Symbol;
            if (stringMethod == null || (!_pxContext.StringFormat.Contains(stringMethod) && !_pxContext.StringConcat.Contains(stringMethod)))
                return false;

            return true;
        }

19 View Source File : MissingTypeListAttributeFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica

private async Task<Doreplacedent> InsertTypeAttributeAsync(Doreplacedent doreplacedent, SyntaxNode root, PropertyDeclarationSyntax propertyDeclaration,
															  CancellationToken cancellationToken)
		{
			cancellationToken.ThrowIfCancellationRequested();

			var semanticModel = await doreplacedent.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
			IPropertySymbol property = semanticModel?.GetDeclaredSymbol(propertyDeclaration, cancellationToken);

			if (property == null)
				return doreplacedent;

			var pxContext = new PXContext(semanticModel.Compilation, codereplacedysisSettings: null);
			var lists = new List<INamedTypeSymbol> {
									pxContext.AttributeTypes.PXIntListAttribute.Type,
									pxContext.AttributeTypes.PXStringListAttribute.Type };

			var attributeTypes = property.GetAttributes()
										 .Select(a => a.AttributeClreplaced);
			var listAttribute = attributeTypes.FirstOrDefault(attributeType =>
													lists.Any(lAttribute => attributeType.InheritsFromOrEquals(lAttribute, true)));

			cancellationToken.ThrowIfCancellationRequested();

			string attributeIdentifier = listAttribute.InheritsFromOrEquals(pxContext.AttributeTypes.PXIntListAttribute.Type)
				? pxContext.FieldAttributes.PXIntAttribute.Name
				: pxContext.FieldAttributes.PXStringAttribute.Name;

			AttributeSyntax attributeNode =
				SyntaxFactory.Attribute(
					SyntaxFactory.IdentifierName(attributeIdentifier));

			var attributes = propertyDeclaration.AttributeLists.Add(
				   SyntaxFactory.AttributeList(
					   SyntaxFactory.SingletonSeparatedList(attributeNode)));

			var modifiedRoot = root.ReplaceNode(propertyDeclaration,
												propertyDeclaration.WithAttributeLists(attributes));
			return doreplacedent.WithSyntaxRoot(modifiedRoot);
		}

19 View Source File : PXGraphCreationForBqlQueriesFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica

private Task<Doreplacedent> ReplaceIdentifier(Doreplacedent doreplacedent, SyntaxNode root, ArgumentSyntax nodeToReplace,
			string identifierName, bool isGraphExtension, CancellationToken cancellationToken)
		{
			cancellationToken.ThrowIfCancellationRequested();

			ExpressionSyntax newExpression;
			if (identifierName == "this")
				newExpression = SyntaxFactory.ThisExpression();
			else
				newExpression = SyntaxFactory.IdentifierName(identifierName);

			if (isGraphExtension)
			{
				newExpression = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, newExpression,
					SyntaxFactory.IdentifierName("Base"));
			}

			var newNode = nodeToReplace.WithExpression(newExpression);
			var newRoot = root.ReplaceNode(nodeToReplace, newNode);

			return Task.FromResult(doreplacedent.WithSyntaxRoot(newRoot));
		}

19 View Source File : PXGraphDeclarationTypeParameterFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica

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;
		}

private void CheckProcessingDelegates(PXGraphSemanticModel pxGraph, WalkerForGraphreplacedyzer walker, CancellationToken cancellation)
        {
            cancellation.ThrowIfCancellationRequested();

            if (!pxGraph.IsProcessing)
            {
                return;
            }

            var processingViews = pxGraph.Views.Where(v => v.IsProcessing);

            foreach (var viewDel in processingViews)
            {
                var finallyDelegates = viewDel.FinallyProcessDelegates.Where(d => d.Node != null);

                foreach (var finDel in finallyDelegates)
                {
                    cancellation.ThrowIfCancellationRequested();
                    walker.Visit(finDel.Node);
                }

                var parametersDelegates = viewDel.ParametersDelegates.Where(d => d.Node != null);

                foreach (var parDel in parametersDelegates)
                {
                    cancellation.ThrowIfCancellationRequested();
                    walker.Visit(parDel.Node);
                }

                var processDelegates = viewDel.ProcessDelegates.Where(d => d.Node != null);

                foreach (var processDel in processDelegates)
                {
                    cancellation.ThrowIfCancellationRequested();
                    walker.Visit(processDel.Node);
                }
            }
        }

19 View Source File : ParametersCounterSyntaxWalker.cs
License : GNU General Public License v3.0
Project Creator : Acumatica

public override void VisitGenericName(GenericNameSyntax genericNode)
			{
				_cancellationToken.ThrowIfCancellationRequested();

				SymbolInfo symbolInfo = _syntaxContext.SemanticModel.GetSymbolInfo(genericNode, _cancellationToken);

				if (!(symbolInfo.Symbol is ITypeSymbol typeSymbol))
				{
					_cancellationToken.ThrowIfCancellationRequested();
					base.VisitGenericName(genericNode);
					return;
				}

				if (genericNode.IsUnboundGenericName)
					typeSymbol = typeSymbol.OriginalDefinition;

				if (!ParametersCounter.CountParametersInTypeSymbolForGenericNode(typeSymbol, _cancellationToken))
					return;

				_cancellationToken.ThrowIfCancellationRequested();
				base.VisitGenericName(genericNode);
			}

19 View Source File : InternalApiCallsWalker.cs
License : GNU General Public License v3.0
Project Creator : Acumatica

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

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

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

19 View Source File : DacExtensionDefaultAttributeFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica

private async Task<Doreplacedent> AddToAttributePersistingCheckNothing(Doreplacedent doreplacedent, TextSpan span, bool isBoundField, CancellationToken cancellationToken)
		{
			SyntaxNode root = await doreplacedent.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

			if (!(root?.FindNode(span) is AttributeSyntax attributeNode))
				return doreplacedent;

			if (!(attributeNode.Parent is AttributeListSyntax attributeList))
				return doreplacedent;

			cancellationToken.ThrowIfCancellationRequested();

			SyntaxGenerator generator = SyntaxGenerator.GetGenerator(doreplacedent);

			var memberAccessExpression = generator.MemberAccessExpression(generator.IdentifierName(TypeNames.PXPersistingCheck),
																		  generator.IdentifierName(TypeNames.PersistingCheckNothing));
			var persistingAttributeArgument = generator.AttributeArgument(TypeNames.PersistingCheck,
																		  memberAccessExpression) as AttributeArgumentSyntax;

			SyntaxNode modifiedRoot;

			if (attributeNode.ArgumentList != null)
			{
				AttributeArgumentSyntax argument = GetArgumentFromAttribute();

				if (argument != null)
				{
					persistingAttributeArgument = argument.ReplaceNode(argument.Expression, memberAccessExpression);
					var newAttributeNode = attributeNode.ReplaceNode(argument, persistingAttributeArgument);
					var newAttributeList = attributeList.ReplaceNode(attributeNode, newAttributeNode);
					modifiedRoot = root.ReplaceNode(attributeList, newAttributeList);
				}
				else
				{
					var newAttributeList = generator.AddAttributeArguments(attributeNode, new SyntaxNode[] { persistingAttributeArgument }) as AttributeListSyntax;
					modifiedRoot = root.ReplaceNode(attributeNode, newAttributeList.Attributes[0]);
				}
			}
			else
			{
				AttributeListSyntax newAttribute = generator.InsertAttributeArguments(attributeNode, 1, new SyntaxNode[] { persistingAttributeArgument }) as AttributeListSyntax;
				modifiedRoot = root.ReplaceNode(attributeNode, newAttribute.Attributes[0]);
			}

			return doreplacedent.WithSyntaxRoot(modifiedRoot);

			AttributeArgumentSyntax GetArgumentFromAttribute()
			{
				foreach (AttributeArgumentSyntax _argument in attributeNode.ArgumentList.Arguments)
				{
					if (_argument.NameEquals != null
						&& _argument.NameEquals.Name.Identifier.Text.Contains(TypeNames.PersistingCheck))
					{
						return _argument;
					}
				}
				return null;
			}

		}

19 View Source File : DacPropertyAttributesAnalyzer.cs
License : GNU General Public License v3.0
Project Creator : Acumatica

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;
		}

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);
		}

private Task<Doreplacedent> RemoveAllOtherAttributesFromPropertyAsync(Doreplacedent doreplacedent, SyntaxNode root, AttributeSyntax attributeNode,
																		 PropertyDeclarationSyntax propertyDeclaration, SemanticModel semanticModel,
																		 Func<FieldTypeAttributeInfo, bool> removePredicate, CancellationToken cancellationToken)
		{	
			var rewriterWalker = new MultipleAttributesRemover(doreplacedent, semanticModel, attributeNode, removePredicate, cancellationToken);
			var propertyModified = rewriterWalker.Visit(propertyDeclaration) as PropertyDeclarationSyntax;

			cancellationToken.ThrowIfCancellationRequested();

			var modifiedRoot = root.ReplaceNode(propertyDeclaration, propertyModified);
			return Task.FromResult(doreplacedent.WithSyntaxRoot(modifiedRoot));		
		}

19 View Source File : IncorrectDeclarationOfDacKeyFix.cs
License : GNU General Public License v3.0
Project Creator : Acumatica

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