public async Task BranchUsingLocalGit(long buildId, string branchName) { VcsCommit commit = await GetCommitInformationByBuildId(buildId); if (commit == null) { Log.Info("Could not find commit for build. Skipping creation of branch step."); return; } IGitRepository gitRepository = _gitRepositoryFactory.Clone(commit); if (gitRepository == null) { throw new Exception("Unable to Clone Git Repository and create branch"); } if (gitRepository.AddBranch(branchName, commit.CommitSha)) { gitRepository.CheckoutBranch(branchName); gitRepository.Push(branchName); } gitRepository.DeleteFolder(); }
public async Task BranchUsingGitLabApi(long buildId, string branchName) { VcsCommit commit = await GetCommitInformationByBuildId(buildId); if (commit == null) { Log.Info("Could not find commit for build. Skipping creation of branch step."); return; } var gitLabClient = _gitLabClientFactory.GetGitLabClient(); var project = gitLabClient.Projects.Get(commit.RepositoryNameWithNamespace); var repo = gitLabClient.GetRepository(project.Id); var existingBranches = repo.Branches.All(); if (!existingBranches.Any(b => string.Equals(b.Name, branchName, StringComparison.InvariantCultureIgnoreCase))) { repo.Branches.Create(new BranchCreate() { Name = branchName, Ref = commit.CommitSha }); } }
/// <summary> /// Транзакция: операции вставки или удаления /// </summary> /// <param name="commit"></param> /// <param name="transactionType"></param> public void Transaction(VcsCommit commit, VcsStorageTransactionType transactionType) { lock (_lock) { switch (transactionType) { case VcsStorageTransactionType.Commit: Insert(commit); break; case VcsStorageTransactionType.Remove: Remove(commit); break; } } }
/// <summary> /// Коммит файла в хранилище /// </summary> /// <param name="commit">Путь файла от корня хранилища</param> /// <param name="stream">Данные для записи</param> /// <returns>Внутренний идентификатор коммита</returns> public VcsCommit Commit(VcsCommit commit, Stream stream) { var realCommit = new VcsCommit {File = commit.File, Code = ComputeCommitCode(stream), Branch = commit.Branch}; Transaction(realCommit, VcsStorageTransactionType.Commit); RollRealWriting(realCommit, stream); return realCommit; }
/// <summary> /// Удалить определённые версии файла из хранилища /// </summary> /// <param name="commit">Целевой элемент</param> /// <param name="commits">Перечисление коммитов</param> public void Remove(VcsCommit commit, IEnumerable<string> commits) { foreach (var c in commits) { Transaction( new VcsCommit { Code = c, File = commit.File }, VcsStorageTransactionType.Remove ); } }
/// <summary> /// Поиск представления элемента в хранилище /// </summary> /// <param name="commit"></param> /// <param name="excludeRemoved"></param> /// <returns></returns> private IEnumerable<VcsCommit> Find(VcsCommit commit, bool excludeRemoved) { var container = GetElement(commit); if (container == null) { return new List<VcsCommit>(); } return new List<VcsCommit>(container.Descendants("Commit").Where( el => el.IsRemovedElement() == !excludeRemoved ).Select( el => new VcsCommit { Code = el.Attribute("Code").Value, File = new FileDescriptor { Version = el.Attribute("Code").Value, Path = container.Attribute("Filename").Value, Filename = Path.GetFileName(container.Attribute("Filename").Value), DateTime = DateTime.Parse(el.Attribute("DateTime").Value), Owner = el.Attribute("Commiter").Value } } )); }
public async Task <VcsCommit> GetCommitInformationByBuildId(long buildId) { Log.Info(string.Format("Get Commit Information for Build: {0}", buildId)); Build build = await _client.Builds.ById(buildId); if (!build.Revisions.Any()) { Log.Debug("Build doesn't have any VCS data"); return(null); } BuildConfig currentBuildConfig = await _client.BuildConfigs.GetByConfigurationId(build.BuildConfig.Id); Log.Debug("Build Loaded from TeamCity"); string commitSha = build.Revisions.First().Version; Log.Debug(string.Format("Commit SHA from first Revision: {0}", commitSha)); //use VCS Root from the current state of Build Config, instead of the old version, as it could have been moved to a different repository var vcsRootId = currentBuildConfig.VcsRootEntries.VcsRootEntry.First().VcsRoot.Id; Log.Debug(string.Format("Get VCSRoot by Id: {0}", vcsRootId)); VcsRoot vcsRoot = await _client.VcsRoots.ById(vcsRootId); Log.Debug(string.Format("VCSRoot: {0}", vcsRoot)); //build configs don't have resolved system parameters, so manually inject it as a workaround. //Another way to get resolved system parameters is to use ResultingProperties API call for the latest build of the config currentBuildConfig.Parameters.Property.Add(new Property { Name = ParameterName.SystemTeamcityProjectName, Value = currentBuildConfig.Project.Name }); VcsCommit commit = new VcsCommit(vcsRoot, currentBuildConfig.Parameters.Property, commitSha); return(commit); }
public IGitRepository Clone(VcsCommit commitInfo) { return(Clone(commitInfo.AuthenticationType, commitInfo.RepositoryLocation)); }
/// <summary> /// Поиск представления элемента в хранилище /// </summary> /// <returns></returns> public IEnumerable<VcsCommit> Find(VcsCommit commit) { return Find(commit, true); }
/// <summary> /// Проверяет существование элемента в маппинге. Если указан коммит, /// то проверяет жёстко по коммиту /// </summary> /// <param name="commit">Представление элемента</param> /// <returns></returns> public bool Exists(VcsCommit commit) { var found = Find(commit); if (!found.Any()) { return false; } // если код коммита имеет некорректную форму или не указан, а элемент // найден - просто вернём true if (!VcsStorageUtils.CorrectCommitCode(commit)) { return true; } return found.Any(c => c.Code == commit.Code); }
/// <summary> /// Возвращает описание элемента из карты, если таковой существует /// </summary> /// <param name="commit">Представление элемента</param> /// <returns>XML-контейнер элемента</returns> private XElement GetElement(VcsCommit commit) { return Map.XPathSelectElement("/Element[@Filename='" + commit.File.Path + "' and @Branch='" + commit.Branch + "']"); }
/// <summary> /// /// </summary> /// <param name="commit"></param> public void Insert(VcsCommit commit) { var container = GetElement(commit); if (container == null) { container = new XElement("Element"); container.SetAttributeValue("Filename", commit.File.Path); container.SetAttributeValue("Branch", commit.Branch); container.SetAttributeValue("TotalCommits", 0); Map.Add(container); } var xmlCommit = new XElement("Commit"); xmlCommit.SetAttributeValue("Code", commit.Code); xmlCommit.SetAttributeValue("DateTime", DateTime.Now); xmlCommit.SetAttributeValue("Commiter", commit.Commiter); IncrementElementCommits(container); container.SetAttributeValue("LastCommit", commit.Code); container.AddFirst(xmlCommit); }
/// <summary> /// Удаляет элемент из маппинга. Если указан коммит, то только /// данный коммит, в противном случае - весь элемент /// </summary> /// <param name="commit">Представление коммита</param> public void Remove(VcsCommit commit) { var container = GetElement(commit); if (!VcsStorageUtils.CorrectCommitCode(commit)) { container.SetAttributeValue("Removed", true); } else { var xmlCommit = container.XPathSelectElement("/Element/Commit[@Code='" + commit.Code + "']"); if (xmlCommit != null) { xmlCommit.SetAttributeValue("Removed", true); } if (!container.Elements().All(el => el.IsRemovedElement())) { container.SetAttributeValue("Removed", true); } } }
/// <summary> /// Проверяет наличие коммита в системе /// </summary> /// <param name="commit">Представление элемента</param> /// <returns>True, если коммит присутствует</returns> private bool CommitExists(VcsCommit commit) { return _mapper.Find(commit).Any(c => c.Code == commit.Code); }
/// <summary> /// Производит реверт элемента на коммит, указанный в поле IVcsStorageElement::commit /// </summary> /// <param name="commit">Представление элемента</param> public VcsCommit Revert(VcsCommit commit) { if (!VcsStorageUtils.CorrectCommitCode(commit)) { throw new Exception("Incorrect commit code!"); } if (!CommitExists(commit)) { throw new Exception("Transaction not exists!"); } var sourceStream = Engine.Get(new FileDescriptor { Path = Path.Combine(VcsStorageDefaults.ObjFilesDirectory, commit.Code) }).GetStream(FileAccess.Read); var revertedCode = ComputeCommitCode(sourceStream); var reverted = new VcsCommit { File = new FileDescriptor { Path = Path.Combine(VcsStorageDefaults.ObjFilesDirectory, revertedCode) }, Code = revertedCode }; Transaction(commit, VcsStorageTransactionType.Revert); Engine.Set(reverted.File, sourceStream); return reverted; }
/// <summary> /// Проверяет код коммита на валидность /// </summary> /// <param name="commit"></param> /// <returns>True, если код верен</returns> public static bool CorrectCommitCode(VcsCommit commit) { return !string.IsNullOrWhiteSpace(commit.Code); }
/// <summary> /// Возвращает поток на чтение файла из хранилища /// </summary> /// <param name="commit"></param> /// <returns></returns> public Stream Pick(VcsCommit commit) { return VcsStorageUtils.CorrectCommitCode(commit) ? PickCommit(commit) : PickLatestCommit(commit); }
/// <summary> /// Регистрирует транзакцию /// </summary> /// <param name="commit">Представление коммита</param> /// <param name="type">Тип транзакции</param> private void Transaction(VcsCommit commit, VcsStorageTransactionType type) { _logger.Transaction(new VcsStorageTransaction { Commit = commit, DateTime = DateTime.Now, Filename = commit.File.Path, Type = type }); _mapper.Transaction(commit, type); }
/// <summary> /// Производит реальной прокат записи на диск /// </summary> /// <param name="commit">Представление элемента</param> /// <param name="stream">Исходный поток</param> private void RollRealWriting(VcsCommit commit, Stream stream) { Engine.Set(new FileDescriptor { Path = Path.Combine(VcsStorageDefaults.ObjFilesDirectory, commit.Code) }, stream); }
/// <summary> /// Возвращает наиболее позднюю версию элемента из хранилища /// </summary> /// <param name="commit"></param> /// <returns></returns> private Stream PickLatestCommit(VcsCommit commit) { var latestVersion = GetLatestVersion(commit); if (latestVersion == null) { return null; } return Engine.Get(new FileDescriptor { Path = Path.Combine(VcsStorageDefaults.ObjFilesDirectory, latestVersion.Code) }).GetStream(FileAccess.Read); }
/// <summary> /// Возвращает поток до версии файла, если он существует /// </summary> /// <param name="commit"></param> /// <returns></returns> private Stream PickCommit(VcsCommit commit) { if (_mapper.Exists(commit)) { return Engine.Get(new FileDescriptor { Path = Path.Combine(VcsStorageDefaults.ObjFilesDirectory, commit.Code) }).GetStream(FileAccess.Read); } return null; }
/// <summary> /// Возвращает актуальную версию элемента /// </summary> /// <param name="commit"></param> /// <returns></returns> private VcsCommit GetLatestVersion(VcsCommit commit) { return _mapper.Find(new VcsCommit {File = commit.File, Branch = commit.Branch}).ToList().FirstOrDefault(); }