<commit_before>using System.Collections.Generic;
using System.Linq;


namespace GitMind.GitModel.Private
{
	internal class AheadBehindService : IAheadBehindService
	{
		public void SetAheadBehind(MRepository repository)
		{
			// Getting all branches, which are active and have both local and remote tracking branches.
			IEnumerable<MSubBranch> activeSubBranches = GetActiveSubBranches(repository);
			IEnumerable<MBranch> bothLocalAndRemoteBranches = GetBranchesWhichAreBothLocalAndRemote(
				repository, activeSubBranches);

			bothLocalAndRemoteBranches.ForEach(b => b.IsLocalAndRemote = true);

			// Mark all commits in local branches as local commit
			MarkLocalCommits(repository);

			// Mark all commits in remote branches as remote commits
			MarkRemoteCommits(repository);

			// Count all commits in all branches to get the local and remote ahead count for a branch 
			CountLocalAndRemoteCommits(repository);
		}


		private static IEnumerable<MSubBranch> GetActiveSubBranches(MRepository repository)
		{
			return repository.SubBranches.Where(b => b.Value.IsActive).Select(b => b.Value);
		}


		private static IEnumerable<MBranch> GetBranchesWhichAreBothLocalAndRemote(
			MRepository repository, IEnumerable<MSubBranch> activeSubBranches)
		{
			return activeSubBranches
				.GroupBy(b => b.BranchId)
				.Where(g => g.Count() == 2 && g.Any(b => b.IsLocal) && g.Any(b => b.IsRemote))
				.Select(g => repository.Branches.First(b => b.Value.Id == g.Key).Value);
		}


		private static void CountLocalAndRemoteCommits(MRepository repository)
		{
			foreach (var branch in repository.Branches)
			{
				int localAheadCount = 0;
				int remoteAheadCount = 0;
				foreach (MCommit commit in branch.Value.Commits)
				{
					if (commit.IsLocalAhead)
					{
						localAheadCount++;
					}
					else if (commit.IsRemoteAhead)
					{
						remoteAheadCount++;
					}
				}

				branch.Value.LocalAheadCount = localAheadCount;
				branch.Value.RemoteAheadCount = remoteAheadCount;
			}
		}


		private static void MarkRemoteCommits(MRepository repository)
		{
			var remoteSubBranches = repository.SubBranches.Where(b => b.Value.IsActive && b.Value.IsRemote);
			remoteSubBranches.ForEach(branch => MarkIsRemoteAhead(branch.Value.TipCommit));
		}


		private static void MarkLocalCommits(MRepository repository)
		{
			var localSubBranches = repository.SubBranches.Where(b => b.Value.IsActive && b.Value.IsLocal);
			localSubBranches.ForEach(branch => MarkIsLocalAhead(branch.Value.TipCommit));
		}


		private static void MarkIsLocalAhead(MCommit commit)
		{
			if (!commit.IsLocalAheadMarker)
			{
				if (!commit.IsUncommitted)
				{
					commit.IsLocalAheadMarker = true;
				}

				foreach (MCommit parent in commit.Parents)
				{
					MarkIsLocalAhead(parent);
				}
			}
		}


		private static void MarkIsRemoteAhead(MCommit commit)
		{
			if (!commit.IsRemoteAheadMarker)
			{
				commit.IsRemoteAheadMarker = true;

				foreach (MCommit parent in commit.Parents)
				{
					MarkIsRemoteAhead(parent);
				}
			}
		}
	}<commit_msg>Change ahead and behind from recursive to iterative code<commit_after>using System.Collections.Generic;
using System.Linq;


namespace GitMind.GitModel.Private
{
	internal class AheadBehindService : IAheadBehindService
	{
		public void SetAheadBehind(MRepository repository)
		{
			// Getting all branches, which are active and have both local and remote tracking branches.
			IEnumerable<MSubBranch> activeSubBranches = GetActiveSubBranches(repository);
			IEnumerable<MBranch> bothLocalAndRemoteBranches = GetBranchesWhichAreBothLocalAndRemote(
				repository, activeSubBranches);

			bothLocalAndRemoteBranches.ForEach(b => b.IsLocalAndRemote = true);

			// Mark all commits in local branches as local commit
			MarkLocalCommits(repository);

			// Mark all commits in remote branches as remote commits
			MarkRemoteCommits(repository);

			// Count all commits in all branches to get the local and remote ahead count for a branch 
			CountLocalAndRemoteCommits(repository);
		}


		private static IEnumerable<MSubBranch> GetActiveSubBranches(MRepository repository)
		{
			return repository.SubBranches.Where(b => b.Value.IsActive).Select(b => b.Value);
		}


		private static IEnumerable<MBranch> GetBranchesWhichAreBothLocalAndRemote(
			MRepository repository, IEnumerable<MSubBranch> activeSubBranches)
		{
			return activeSubBranches
				.GroupBy(b => b.BranchId)
				.Where(g => g.Count() == 2 && g.Any(b => b.IsLocal) && g.Any(b => b.IsRemote))
				.Select(g => repository.Branches.First(b => b.Value.Id == g.Key).Value);
		}


		private static void CountLocalAndRemoteCommits(MRepository repository)
		{
			foreach (var branch in repository.Branches)
			{
				int localAheadCount = 0;
				int remoteAheadCount = 0;
				foreach (MCommit commit in branch.Value.Commits)
				{
					if (commit.IsLocalAhead)
					{
						localAheadCount++;
					}
					else if (commit.IsRemoteAhead)
					{
						remoteAheadCount++;
					}
				}

				branch.Value.LocalAheadCount = localAheadCount;
				branch.Value.RemoteAheadCount = remoteAheadCount;
			}
		}


		private static void MarkRemoteCommits(MRepository repository)
		{
			var remoteSubBranches = repository.SubBranches.Where(b => b.Value.IsActive && b.Value.IsRemote);
			remoteSubBranches.ForEach(branch => MarkIsRemoteAhead(branch.Value.TipCommit));
		}


		private static void MarkLocalCommits(MRepository repository)
		{
			var localSubBranches = repository.SubBranches.Values
				.Where(b => b.IsActive && b.IsLocal);

			localSubBranches.ForEach(branch => MarkIsLocalAhead(branch.TipCommit));
		}


		private static void MarkIsLocalAhead(MCommit commit)
		{
			Stack<MCommit> stack = new Stack<MCommit>();
			stack.Push(commit);

			while (stack.Any())
			{
				commit = stack.Pop();

				if (!commit.IsLocalAheadMarker)
				{
					if (!commit.IsUncommitted)
					{
						commit.IsLocalAheadMarker = true;
					}

					foreach (MCommit parent in commit.Parents)
					{
						stack.Push(parent);
					}
				}
			}


			//if (!commit.IsLocalAheadMarker)
			//{
			//	if (!commit.IsUncommitted)
			//	{
			//		commit.IsLocalAheadMarker = true;
			//	}

			//	foreach (MCommit parent in commit.Parents)
			//	{
			//		MarkIsLocalAhead(parent);
			//	}
			//}
		}


		private static void MarkIsRemoteAhead(MCommit commit)
		{
			Stack<MCommit> stack = new Stack<MCommit>();
			stack.Push(commit);

			while (stack.Any())
			{
				commit = stack.Pop();

				if (!commit.IsRemoteAheadMarker)
				{
					commit.IsRemoteAheadMarker = true;

					foreach (MCommit parent in commit.Parents)
					{
						stack.Push(parent);
					}
				}
			}

			//if (!commit.IsRemoteAheadMarker)
			//{
			//	commit.IsRemoteAheadMarker = true;

			//	foreach (MCommit parent in commit.Parents)
			//	{
			//		MarkIsRemoteAhead(parent);
			//	}
			//}
		}
	}
{'fraction_non_alphanumeric': 0.10175438596491228, 'fraction_numerical': 0.0008771929824561404, 'mean_word_length': 3.4683213585891575, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3217127', 'n_tokens_mistral': 2649, 'n_tokens_neox': 2168, 'n_words': 443}