CmdRunner: Plastic SCM API


소개

Plastic SCM 빌드 시 사용자 및 고객의 요청과 내부 일정에 따라 기능을 추가하므로, 시간과 리소스의 부족 때문에 추가하지 못하는 일부 기능들이 있습니다. 그동안 다행히 커뮤니티의 도움으로 다양한 플러그인과 기능을 개발할 수 있었습니다.

Plastic SCM을 확장하는 방법 중 하나는 명령줄 위에 빌드되는 자동화 계층인 CmdRunner를 사용하는 것입니다. C#을 사용하여 .NET에 빌드되고 Github 리포지토리에서 공개적으로 사용할 수 있으므로 포크 및 기여가 가능합니다.

Plastic SCM의 명령줄에는 툴의 출력을 커스터마이즈할 수 있는 --machinereadable, --format과 같은 매개 변수가 포함되어 있기 때문에 외부 툴을 사용하여 쉽게 파싱할 수 있습니다. Eclipse, IntelliJ, TeamCity, Hudson / Jenkins, Crucible, Bamboo 등의 플러그인은 전부 명령줄 클라이언트 기반이므로 확장 가능성이 많습니다.

시작 전 확인할 사항 이러한 샘플을 사용하려면 사용자 기기에 작동 가능한 Plastic SCM 클라이언트가 설치되어야 합니다. 여기에서 무료 라이센스가 제공됩니다(개발자 최대 5명에게 제공).

Hello world

Code: Samples/HelloWorld.cs

래퍼 레이어의 역할을 가장 효과적으로 알려주기 위해 래퍼 레이어로 무엇을 할 수 있는지 보여드리겠습니다. 다음은 간단한 예시입니다.

string cmVersion = CmdRunner.ExecuteCommandWithStringResult("cm version", Environment.CurrentDirectory);
Console.WriteLine(string.Format("The cm version is: {0}", cmVersion));

.NET의 실행 방식에 익숙하다면 Plastic에서 이러한 모든 논리를 단순하고 정적인 방식으로 추상화한 것을 확인할 수 있을 것입니다. Plastic에서는 표준 출력에서 일반적으로 얻을 수 있는 출력을 복구합니다. 특정 서버에서 사용할 수 있는 모든 리포지토리를 나열하는 것과 같이 조금 더 중요한 작업을 수행할 수 있습니다.

string server = "remoteserver:8087";
string repoList = CmdRunner.ExecuteCommandWithStringResult(string.Format("cm repository list {0}", server), Environment.CurrentDirectory);

Console.WriteLine(string.Format("{0}", repoList));

이 작은 텍스트 조각이 다음과 같은 형태로 출력됩니다.

The cm version is: 5.4.16.633 1 default localhost:8084 4 cmdSamplesToyRepo localhost:8084

여러 인수를 어떻게 처리하는지도 보셨나요? 이 섹션을 끝내기 전에 간단히 설명하자면 CmdRunner를 사용하여 difftool 또는 semanticmerge와 같은 다른 프로그램을 실행할 수 있습니다. PATH에서 사용할 수 있는 경우 이를 직접 호출(즉, 탐색기)할 수 있으며, 그렇지 않으면 실행 파일의 전체 경로를 사용하여 호출할 수 있습니다.


시작하기

github에서 리포지토리를 다운로드하여 시작할 수 있습니다. 두 가지 방법으로 코드를 가져올 수 있습니다.

  1. zip 파일 형식의 가장 최근 변경사항을 다운로드합니다.
  2. git-sync(여기에서 자세한 내용 확인)를 사용하여 로컬 리포지토리와 다음을 동기화합니다.

    $ cm repository create plastic-cmdrunner $ cm sync plastic-cmdrunner@localhost:8087 git https://github.com/PlasticSCM/plastic-cmdrunner.git

자신의 명령으로 이를 확장하려는 경우 리포지토리를 포크하여 동기화할 자신의 리포지토리를 제공하고, 나중에 다시 기여하려는 경우 가져오기 요청을 수행하면 변경사항이 검토되고 부모 리포지토리에 다시 병합됩니다.

명령

중요: git-sync를 사용하려면 Plastic SCM 4.2 이상이 필요합니다.

패키지를 다운로드한 후에는 두 가지 프로젝트가 포함된 Visual Studio 2010 솔루션을 찾을 수 있습니다.

  1. 라이브러리가 포함된 CmdRunner
  2. 이 문서에서 설명하는 샘플이 모두 포함된 샘플

모든 샘플에는 고유의 주 메서드가 있으므로 Visual Studio에서 프로젝트 속성으로 이동하여 실행할 샘플을 선택하면 됩니다.

Visual Studio - 실행할 샘플 선택


첫 접근 방식: 브랜치 나열

Code: Samples/ListBranches.cs

이 샘플에서는 리포지토리에서 사용할 수 있는 모든 브랜치를 나열합니다. cm find에 대한 자세한 내용은 이 가이드를 확인하십시오.

string cmdResult = CmdRunner.ExecuteCommandWithStringResult(
    string.Format("cm find branch on repositories '{0}' --format={{id}}#{{name}} --nototal", repository),
    Environment.CurrentDirectory);

ArrayList results = SampleHelper.GetListResults(cmdResult, true);
List<Branch> branches = GetBranchListFromCmdResult(results);

foreach (Branch branch in branches)
    Console.WriteLine(branch);

이 코드로 리포지토리에 대한 기본 쿼리를 수행합니다. 명령의 원시 출력은 다음과 같이 표시됩니다.

3#/main 12#/main/task0 13#/main/task1 14#/main/task2 15#/main/task3 16#/main/task4 17#/main/task5 18#/main/task6 19#/main/task7 20#/main/task8 21#/main/task9

그런 다음, 샘플 도우미를 사용하여 메서드 GetListResults로 출력을 파싱하고 문자열 목록으로 변환합니다. 마지막으로, 각 요소마다 새 브랜치 객체를 생성합니다.

public class Branch
{
    public string Id { get; set; }
    public string Name { get; set; }

    public Branch(string output)
    {
        string[] parsed = output.Split('#');
        Id = parsed[0];
        Name = parsed[1];
    }

    public override string ToString()
    {
        return Id + " - " + Name;
    }

    public override bool Equals(object obj)
    {
        if (!(obj is Branch))
            return base.Equals(obj);

        return ((Branch)obj).Name.Equals(Name);
    }
}

이제 이 객체에는 이름 및 서버의 정보와 다음 샘플에서 브랜치들을 비교하는 데 사용할 수 있는 동일한 재정의가 포함됩니다. cm find에서 가져올 수 있는 모든 매개 변수로 이 정보를 확장할 수 있습니다.


다양한 서버 다루기: 복제기

Code: Samples/Replicator.cs

이전 샘플과 브랜치 객체를 기반으로 이제 한 리포지토리에서 생성된 변경사항을 다른 리포지토리로 복제해 보겠습니다. 브랜치를 복제하려면 브랜치의 전체 사양과 대상 리포지토리가 필요합니다. 이 작업은 다음 코드를 사용해 처리할 수 있습니다.

private static ReplicationResult Replicate(Branch branch, string repository, string secondRepository)
{
    Console.WriteLine("Replicating branch {0}", branch.Name);
 
    string cmdResult = CmdRunner.ExecuteCommandWithStringResult(
      string.Format("cm replicate \"br:{0}@{1}\" \"rep:{2}\"", 
        branch.Name, repository, secondRepository),
      Environment.CurrentDirectory);
 
    return new ReplicationResult(SampleHelper.GetListResults(cmdResult, true), branch);
}

복제 명령을 호출하면 결과가 파싱되고 Replication Result라는 단순한 클래스로 변환됩니다. Replicate 명령의 원시 출력은 다음과 같이 표시됩니다.

DataWritten Items 1 Revs 0 ACLs 0 Changesets 0 Labels 0 Applied labels 0 Links 0 Applied links 0 Attributes 0 Applied attributes 0 Reviews 0 Review comments 0 branch /main/task001

대상 리포지토리에 새 브랜치가 생성되면 마지막에 이름이 표시됩니다. 명령을 완료하면 이전 샘플과 같이 결과를 파싱하여 각 작업의 결과와 함께 새 ReplicationResult 객체를 생성합니다.

class ReplicationResult
{
    public long Items { get; set; }
    public Branch Branch { get; set; }
 
    public ReplicationResult(ArrayList cmdResult, Branch branch)
    {
        Branch = branch;
        string buffer = (string)cmdResult[1];
        Items = long.Parse(buffer.Substring(buffer.LastIndexOf(' ')));
    }
}

복제 결과에는 복제된 항목의 수와 관련 브랜치가 포함되어 있습니다. 이는 이전에 표시된 나머지 항목으로 확장될 수 있습니다.

마지막으로 전체 복제에 대한 간단한 보고서가 생성됩니다.

private static void PrintReplicationResult(List<ReplicationResult> resultList)
{
    Console.WriteLine("Branches replicated: {0}" , resultList.Count);
    foreach (ReplicationResult item in resultList)
        Console.WriteLine("- {0} ({1} item{2})", 
            item.Branch.Name, item.Items, item.Items == 1 ? "" : "s");
}

복제 출력은 다음과 같이 표시됩니다.

Replicating branch /main Replicating branch /main/task0 Replicating branch /main/task1 Replicating branch /main/task2 Replicating branch /main/task3 Replicating branch /main/task4 Replication complete Branches replicated: 6 - /main (0 items) - /main/task0 (3 items) - /main/task1 (4 items) - /main/task2 (2 items) - /main/task3 (3 items) - /main/task4 (2 items)

알림 추가: 알림 프로그램

Code: Samples/Notifier.cs

이전 예에 이어, 이제 브랜치의 변경사항을 한 서버에서 다른 서버로 복제할 수 있게 변경사항을 추적해보겠습니다. 이 시나리오의 경우, 코드가 한 리포지토리에서 변경사항을 시뮬레이션하므로 다른 서버에서 알림을 받을 수 있습니다.

새 브랜치가 있는지 먼저 확인해야 하므로 두 서버에서 브랜치를 찾고 소스에만 있는 브랜치를 추가합니다.

List<Branch> GetBranchesToSync()
{
    List<Branch> srcBranches = GetBranchesFromRepo(mSampleRep);
    List<Branch> dstBranches = GetBranchesFromRepo(mSecondRep);
    List<Branch> newBranches = new List<Branch>();
 
    foreach (Branch item in srcBranches)
    {
        if (!dstBranches.Contains(item))
        {
            newBranches.Add(item);
            continue;
        }
                
        if (HasChangesInBranch(item))
            newBranches.Add(item);
    }
 
    return newBranches;
}

다음 단계로 공통 브랜치에 변경사항이 있는지 확인합니다. 변경사항이 있는지 확인하는 가장 쉬운 옵션은 다시 cm find를 사용하는 것입니다.

private bool HasChangesInBranch(Branch branch)
{
    string srcResult = CmdRunner.ExecuteCommandWithStringResult(
        string.Format("cm find changeset where branch = 'br:{0}' on repositories '{1}' --format={{id}} --nototal", 
          branch.Name, mSampleRep),
        Environment.CurrentDirectory);
 
    ArrayList srcResults = SampleHelper.GetListResults(srcResult, true);
 
    string dstResult = CmdRunner.ExecuteCommandWithStringResult(
        string.Format("cm find changeset where branch = 'br:{0}' on repositories '{1}' --format={{id}} --nototal", 
          branch.Name, mSecondRep),
        Environment.CurrentDirectory);
 
    ArrayList dstResults = SampleHelper.GetListResults(dstResult, true);
 
    return srcResults.Count != dstResults.Count;
}

모든 체인지 세트를 가져왔으면 체인지 세트를 비교하고, 일치하지 않는 경우 브랜치를 복제해야 합니다. 이 모든 프로세스는 말풍선으로 사용자에게 표시됩니다.

복제 프로세스

말풍선을 클릭하면 복제 프로세스가 시작됩니다. 다른 리포지토리에서 작업을 시뮬레이션하려는 경우, 계속해서 항목을 추가하고 체크인하는 백그라운드 스레드가 있어 변경사항이 표시되기 시작하는 것을 확인할 수 있습니다. 이 샘플에서는 스레드 번호를 추가했습니다. 이미지에서 스레드 9가 주 스레드이고 스레드 10이 백그라운드 스레드입니다.

백그라운드 스레드


로컬 변경사항 추적: CMbox

Code: Samples/CMbox/CMbox.cs

이 샘플에서는 로컬 파일 변경사항을 추적하고 자동으로 커밋하여 Plastic SCM을 Dropbox와 유사한 트레이 앱으로 변환하는 방법을 소개합니다. Dropbox의 성공 사유 중 하나는 대부분의 작업이 백그라운드에서 자동으로 수행되어 간편하고 사용자 상호작용이 거의 필요하지 않기 때문입니다.

가장 먼저 팝업 창을 구성하고 구성 변수에 대한 서버 정보를 가져와야 합니다. 구성 코드 IsSimulation을 변경하지 않으면 변수가 참으로 설정되고 파일이 임시 워크스페이스에 자동으로 추가 및 변경되므로 별도의 작업 없이 파일이 추가되고 변경되는 것을 확인할 수 있습니다.

public CMbox()
{
    ConfigureMenu();
    string server = Configuration.ServerName;
    mSampleRep = SampleHelper.GenerateEmptyRepository(server);
 
    if (Configuration.IsSimulation)
        CMboxHelper.StartSimulation();
}

구성이 완료되면 CommitUpdates 함수를 10초마다 호출합니다. 이 함수는 가장 먼저 cm status 명령을 사용하여 워크스페이스의 기존 변경사항을 찾습니다.

private List<Change> GetChanges()
{
    List<Change> changes = new List<Change>();
    string cmdResult = CmdRunner.ExecuteCommandWithStringResult(
            string.Format("cm status --all --machinereadable"),
            SampleHelper.GetWorkspace());
 
    ArrayList results = SampleHelper.GetListResults(cmdResult, true);
    for (int i = 1; i <  results.Count; i++)
        changes.Add(new Change((string)results[i]));
 
    return changes;
}

cm status 명령을 machinereadable 조정값과 함께 사용하면 다음과 유사한 출력을 얻게 됩니다.

STATUS 4 cmdSample5d4ce30 localhost:8084 PR c:\Users\rbisbe\AppData\Local\Temp\c10d4d2e-1e14-43e4-af1d-a24df76176d5\sampleb165621 False NO_MERGES PR c:\Users\rbisbe\AppData\Local\Temp\c10d4d2e-1e14-43e4-af1d-a24df76176d5\samplef3390c5 False NO_MERGES

생성된 출력은 앞서 본 것처럼 ArrayList로 변환되고 각 줄은 단일 Change 요소로 파싱됩니다.



Code: /Samples/CMbox/Change.cs

class Change
{
    public string Name { get; set; }
    public string FullPath { get; set; }
    public ChangeType ChangeType { get; set; }
 
    public Change(string resultRow)
    {
        string[] separated = resultRow.Split(' ');
        ChangeType = GetFromString(separated[0]);
        FullPath = separated[1];
        Name = Path.GetFileName(separated[1]);
    }
 
    private ChangeType GetFromString(string source)
    {
        switch (source.ToUpperInvariant())
        {
            case "AD+LD":
            case "LD+CO":
                return CmdRunnerExamples.ChangeType.Deleted;
            case "PR":
            case "AD":
                return CmdRunnerExamples.ChangeType.Added;
            case "CO":
                return CmdRunnerExamples.ChangeType.Changed;
            default:
                return CmdRunnerExamples.ChangeType.None;
        }
    }
}

변경사항에는 항목의 이름(말풍선 표시용), 항목의 전체 경로가 있고 마지막으로 결과를 파싱해서 복구한 변경 유형이 있습니다.

변경사항이 복구되고 체크인되지 않은 변경사항이 있으면, 체크인 작업이 완료되고 마지막에 사용자에게 알림이 옵니다.

private void CheckinUpdates(object sender, EventArgs e)
{
    List<Change> mChanges = GetChanges();
    if (mChanges.Count == 0)
        return;
 
    StringBuilder builder = new StringBuilder();
    foreach (var item in mChanges)
        builder.Append(string.Format("{0} {1}\n", item.ChangeType, item.Name));
 
    foreach (var item in mChanges)
    {
        if (item.ChangeType == ChangeType.Added)
            CmdRunner.ExecuteCommandWithStringResult(
                string.Format("cm add {0}", item.Name),
                SampleHelper.GetWorkspace());
 
        if (item.ChangeType == ChangeType.Deleted)
            CmdRunner.ExecuteCommandWithStringResult(
                string.Format("cm rm {0}", item.Name),
                SampleHelper.GetWorkspace());
    }
 
    CmdRunner.ExecuteCommandWithStringResult("cm ci ",
        SampleHelper.GetWorkspace());
 
    mTrayIcon.ShowBalloonTip(3, string.Format("{0} new changes saved", mChanges.Count),
            string.Format("The following changes have been checked in.\n{0}",
            builder.ToString()),
            ToolTipIcon.Info);
 }

이 샘플에서는 cm addcm rm 명령을 사용하여 추가 및 삭제된 것으로 표시된 항목도 추가 및 제거합니다.

알림에는 체크인된 변경사항의 수와 각 변경사항에 관한 간단한 설명이 포함되어 있습니다.

알림: 변경사항 수


게임용 소스 제어

Code: Samples/Game.cs

이 샘플에서는 소스 제어를 게임 세이버로 사용할 것입니다. 따라서 수준을 변경할 때마다 새 체인지 세트가 수준 정보와 함께 생성됩니다. 그러면 항상 이전 게임 상태를 복구할 수 있습니다.

게임용 소스 제어

게임에서 임의의 파일로 된 새 체인지 세트를 생성해 상태를 저장합니다. 체인지 세트 코멘트에 게임 상태가 있습니다.

private void SaveGame()
{
    string item = SampleHelper.AddRandomItem();
    SampleHelper. CheckinItem(item, string.Format("{0}#{1}",
            mColors, mScore));
}

그렇게 하면 게임을 로드할 때 오직 모든 체인지 세트를 찾고 코멘트로 필터링하고 코멘트를 파싱하기만 하면 됩니다. 점수와 색상 번호가 있는 SaveGame이라는 새 클래스에서 각 코멘트를 파싱합니다.

private void ReloadSavedGames()
{
    string cmdResult = CmdRunner.ExecuteCommandWithStringResult(
        string.Format("cm find changeset on repositories '{0}' --format={{comment}} --nototal", 
          textBox1.Text),
          Environment.CurrentDirectory);
 
    ArrayList results = SampleHelper.GetListResults(cmdResult, true);
 
    listBox1.Items.Clear();
    results.RemoveAt(0);
    foreach (string item in results)
        listBox1.Items.Add(new SavedGame(item));
 
}

해당 콘텐츠는 나중에 게임에 로드되므로 게임을 끝냈을 때와 같은 상태로 계속 플레이할 수 있습니다.

로드새로 생성 버튼을 누르면 게임에 대한 새 Plastic SCM 리포지토리를 만들거나 기존 리포지토리에 연결하여 저장된 게임을 불러올 수 있습니다.


자체 PlasticSCM GUI 생성

Code: Samples/MiniGUI/MiniGUI.cs

Plastic SCM의 모든 주요 기능을 명령줄에서 사용할 수 있습니다. 명령줄을 통해 플러그인을 생성하고, 완전한 커스텀 사용자 인터페이스를 생성할 수 있습니다. 이 샘플에서는 대기 중인 변경사항 뷰체인지 세트 목록이 있는 소규모 툴을 만듭니다. 해당 툴을 사용하면 체크인 작업(코멘트 포함)을 수행하고 커밋할 때마다 어떤 파일이 변경되었는지 확인할 수 있습니다. 이 툴의 모습은 다음과 같습니다.

Plastic SCM 미니 GUI

이 탭 항목을 사용하여 파일을 체크인하고 코멘트를 추가할 수 있습니다.

Plastic SCM 미니 GUI - 체인지 세트 탭

이 탭 항목은 체인지 세트와 각 체인지 세트에서 이루어진 여러 변경사항을 표시합니다.

일반적인 사용 동작을 시뮬레이션하므로 콘솔은 자동으로 이루어진 변경사항을 출력합니다.

Plastic SCM 미니 GUI - 콘솔 출력 변경사항

GUI 관련 요소가 아닌 특정 버튼 3개(체크인, 새로고침, 체인지 세트 뷰의 새로고침)의 동작에 중점을 둡니다.


체인지 세트 목록의 새로고침 버튼

이 버튼을 사용하면 체인지 세트 목록이 다시 로드되고 체인지 세트의 내용 목록도 생성됩니다. 이를 위해 cm에서 다음 명령을 사용합니다.

  • find changeset(특정 형식의 체인지 세트를 가져올 때).
  • log(특정 체인지 세트가 주어지면 추가, 이동, 변경 또는 삭제된 항목을 가져올 수 있습니다).
private void RefreshChangesetList(object sender, EventArgs e)
{
    string cmdResult = CmdRunner.ExecuteCommandWithStringResult(
        "cm find changeset --nototal --format=\"{changesetid}#{date}#{comment}\"",
        SampleHelper.GetWorkspace());
 
    ArrayList results = SampleHelper.GetListResults(cmdResult, true);
 
    changesetList.Items.Clear();
    foreach (string item in results)
    {
        Changeset cset = new Changeset(item);
        cmdResult = CmdRunner.ExecuteCommandWithStringResult(
            string.Format("cm log {0} --csFormat=\"{{items}}\" --itemFormat=\"{{path}}#{{fullstatus}}#{{newline}}\"",cset.Id),
            SampleHelper.GetWorkspace());
 
        results = SampleHelper.GetListResults(cmdResult, true);
        foreach (string changedItem in results)
            cset.Changes.Add(new Item(changedItem));
 
        changesetList.Items.Add(cset);
    }
}

명령을 호출하고, 결과를 파싱하고, GUI에 데이터를 표시할 수 있는 새 객체를 생성하는 등 다른 프로세스들과 프로세스가 매우 유사합니다.

Changeset 클래스는 id, 날짜, 코멘트, 변경사항 목록만 포함된 간소화된 표현이며, 단일 cm find 행의 출력을 파싱하는 데 필요한 코드도 포함합니다.

public class Changeset
{
    public string Date { get; set; }
    public string Id { get; set; }
    public string Comment { get; set; }
    public List<Item> Changes { get; set; }
 
    public Changeset(string output)
    {
        string[] parsed = output.Split('#');
        Id = parsed[0];
        Date = parsed[1];
        Comment = parsed[2];
        Changes = new List<Item>();
    }
 
    public override string ToString()
    {
        return string.Format("{0}: cs:{1}", Date, Id);
    }
}

Item 클래스에는 상태와 워크스페이스의 상대 경로가 포함됩니다.

public class Item
{
    public string Path { get; set; }
    public string Status { get; set; }
 
    public Item(string output)
    {
        if (string.IsNullOrEmpty(output))
        {
            Path = string.Empty;
            Status = string.Empty;
            return;
        }
 
        string[] parsed = output.Split('#');
        Path = parsed[0].Replace(SampleHelper.GetWorkspace().ToLowerInvariant(),
            "");
        Status = parsed[1];
    }
 
    public override string ToString()
    {
        if (string.IsNullOrEmpty(Status))
            return string.Empty;
 
        return string.Format("{0} ({1})", Path, Status);
    }
}

대기 중인 변경사항 뷰의 새로고침 버튼

새로고침 버튼을 사용하면 두 목록을 모두 초기화하고, 변경사항 목록을 가져오고, 변경됨에서 추가됨과 삭제됨을 필터링할 수 있습니다. cm에서 cm status 명령만 사용합니다. 이 작업은 CMBox 샘플에서 작업한 것과 동일한 GetChanges입니다.

private void Update(object sender, EventArgs e)
{
    itemsToCommit.Items.Clear();
    itemsNotAdded.Items.Clear();
 
    List<Change> mChanges = GetChanges();
    if (mChanges.Count == 0)
        return;
 
    foreach (var item in mChanges)
    {
        if ((item.ChangeType == ChangeType.Added)
            || (item.ChangeType == ChangeType.Deleted))
        {
            itemsNotAdded.Items.Add(item);
            continue;
        }
 
        itemsToCommit.Items.Add(item);
    }
}

목록에 추가된 항목과 삭제된 항목을 추가하려면 버튼을 더블 클릭하면 됩니다.


대기 중인 변경사항 뷰의 체크인 버튼

체크인 버튼은 추가된 항목을 목록(추가 및 삭제된 항목)에 추가하고 현재 워크스페이스 상태에 대해 체크인 작업을 수행합니다. 마지막으로, 코멘트 텍스트 상자를 지우고 마지막 변경사항으로 목록을 업데이트합니다.

private void Checkin(object sender, EventArgs e)
{
    foreach (Change item in itemsToCommit.Items)
    {
        if (item.ChangeType == ChangeType.Added)
            CmdRunner.ExecuteCommandWithStringResult(
                string.Format("cm add {0}", item.Name),
                SampleHelper.GetWorkspace());
 
        if (item.ChangeType == ChangeType.Deleted)
            CmdRunner.ExecuteCommandWithStringResult(
                string.Format("cm rm {0}", item.Name),
                SampleHelper.GetWorkspace());
    }
 
    CmdRunner.ExecuteCommandWithStringResult(
        string.Format("cm ci -c=\"{0}\"", textBox1.Text),
        SampleHelper.GetWorkspace());
 
    textBox1.Text = string.Empty;
    Update(sender, e);
}

이러한 일부 명령으로 자체 Plastic SCM 클라이언트를 구현할 수 있지만 오류 및 병합 처리 등 GUI에서 내부적으로 하는 수많은 작업은 여전히 처리해야 합니다.


CM 셸 사용

표시된 모든 샘플은 cm.exe 프로세스를 개별적으로 호출하지만, 여러 명령을 수행해야 하는 경우, 결과를 더 빠르게 얻을 수 있습니다.

string repos = CmdRunner.ExecuteCommandWithStringResult("cm repository list",
    Environment.CurrentDirectory, true);

string output;
string error;
CmdRunner.ExecuteCommandWithResult(
    "cm workspace delete .",
    Environment.CurrentDirectory, out output, out error, true);

마지막 부울 값을 보면 셸을 사용하여 명령을 로드하고 있음을 알 수 있고, 이는 하나의 cm.exe만 실행되고 있음을 의미합니다. 실행 중인 셸이 없으면 새 셸이 자동으로 실행됩니다. 이는 다음 시퀀스와 같습니다.

cm shell repository list workspace delete .

도우미 및 구성

Configuration.cs에 Plastic SCM 로컬 서버를 지정하면 모든 코드가 실행 가능한 상태가 됩니다. 단순성을 지향하여 모든 샘플이 작업을 위한 새 리포지토리도 생성하므로 안전한 환경에서 코드를 사용해 볼 수 있습니다.

SampleHelper에는 다음을 위한 코드가 포함됩니다.

  • 빈 리포지토리 생성
  • 브랜치를 포함한 리포지토리 생성
  • 리포지토리 내부에서 항목 추가 및 체크인
  • 워크스페이스 내부에서 항목 추가 및 수정
  • 출력 파싱을 통해 문자열의 ArrayList로 변환
  • 현재 임시 워크스페이스 가져오기

확장

이 코드는 MIT 라이센스에 따른 공개 오픈 소스이므로 다운로드하여 수정하고 필요에 맞게 커스터마이즈할 수 있습니다. Plastic은 사용자의 기여를 감사하게 생각하며, 사용자는 언제든지 자신의 기여를 복제하고 가져오기를 요청할 수 있습니다.


최근 업데이트

2019년 3월 22일
  • cm mkrep와 같이 사용되지 않는 리포지토리 관리 명령에 대한 레퍼런스를 새로운 레퍼런스로 교체했습니다.