GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — GitHub - VerifyTests/DiffEngine: Manages launching and cleanup of diff tools

BranchesTags
Open more actions menu

Latest commit

 

History

2,888 Commits
2,888 Commits

Folders and files

NameName
Last commit message
Last commit date
.github
.github
 
 
docs
docs
 
 
native
native
 
 
src
src
 
 
.editorconfig
.editorconfig
 
 
.gitattributes
.gitattributes
 
 
.gitignore
.gitignore
 
 
claude.md
claude.md
 
 
code_of_conduct.md
code_of_conduct.md
 
 
global.json
global.json
 
 
license.txt
license.txt
 
 
pack-local.ps1
pack-local.ps1
 
 
readme.md
readme.md
 
 
readme.source.md
readme.source.md
 
 
todo.md
todo.md
 
 

Repository files navigation

DiffEngine

Discussions Build status NuGet Status NuGet Status NuGet Status NuGet Status NuGet Status

DiffEngine manages launching and cleanup of diff tools. It is designed to be used by any Snapshot/Approval testing library.

See Milestones for release notes.

Currently used by:

  • ApprovalTests
  • Shouldly
  • Verify

Sponsors

Entity Framework Extensions

Entity Framework Extensions is a major sponsor and is proud to contribute to the development this project.

Entity Framework Extensions

Developed using JetBrains IDEs

JetBrains logo.

Contents

  • NuGet
  • Supported Tools
  • Launching a tool
    • Files derived from another
  • Closing a tool
  • File type detection
  • BuildServerDetector
    • WSL
    • Override in tests
  • Automatic AI detection
    • Programmatic usage
  • Disable for a machine/process
  • Disable in code
  • Disable the tray
  • Icons
  • Tools
  • Tool Order
  • Custom Tool
  • DiffEngineViewer
  • DiffEngineTray
  • Inline snapshots
  • Code versus machine level settings

NuGet

  • https://nuget.org/packages/DiffEngine/

Supported Tools

  • AraxisMerge Windows/OSX (Cost: Paid)
  • BeyondCompare Windows/OSX/Linux (Cost: Paid)
  • CodeCompare Windows (Cost: Free and Paid)
  • Cursor Windows/OSX/Linux (Cost: Free and Paid)
  • DeltaWalker Windows/OSX (Cost: Paid)
  • DiffEngineViewer Windows/OSX/Linux (Cost: Free)
  • Diffinity Windows (Cost: Free with option to donate)
  • ExamDiff Windows (Cost: Paid)
  • Guiffy Windows/OSX (Cost: Paid)
  • Kaleidoscope OSX (Cost: Paid)
  • KDiff3 Windows/OSX (Cost: Free)
  • Meld Windows/OSX/Linux (Cost: Free)
  • MsExcelDiff Windows (Cost: Requires Excel installed)
  • MsWordDiff Windows (Cost: Requires Word installed)
  • Neovim Windows/OSX/Linux (Cost: Free with option to sponsor)
  • P4Merge Windows/OSX/Linux (Cost: Free)
  • Rider Windows/OSX/Linux (Cost: Paid with free option for OSS)
  • SublimeMerge Windows/OSX/Linux (Cost: Paid)
  • TkDiff OSX (Cost: Free)
  • TortoiseGitIDiff Windows (Cost: Free)
  • TortoiseGitMerge Windows (Cost: Free)
  • TortoiseIDiff Windows (Cost: Free)
  • TortoiseMerge Windows (Cost: Free)
  • Vim Windows/OSX (Cost: Free with option to donate)
  • VisualStudio Windows (Cost: Paid and free options)
  • VisualStudioCode Windows/OSX/Linux (Cost: Free)
  • WinMerge Windows (Cost: Free with option to donate)

Launching a tool

A tool can be launched using the following:

await DiffRunner.LaunchAsync(tempFile, targetFile);

snippet source | anchor

Note that this method will respect the above difference behavior in terms of Auto refresh and MDI behaviors.

Files derived from another

A snapshot of a document is often several files: the document, and what was computed from it, such as a png of each page, its text, or a csv per sheet. A file of the second kind can be launched as derived from the first:

// The document first: what is derived from it names it
await DiffRunner.LaunchAsync(documentTempFile, documentTargetFile);

// A file computed from the document, named by the document's temp file
await DiffRunner.LaunchDerivedAsync(pageTempFile, pageTargetFile, documentTempFile, null);

// A file the document no longer produces
await DiffRunner.AddDerivedDeleteAsync(stalePageFile, documentTempFile);

snippet source | anchor

The source is named by its temp file, is launched first, and is named only while it is itself pending.

This changes nothing for most tools: each derived file is launched exactly as Launch would launch it. The exception is DiffEngineViewer when it is drawing the source as a document. It already shows the pages and the text, so the derived files open no tool, do not count towards MaxInstancesToLaunch, and are accepted or discarded together with the document.

Closing a tool

A tool can be closed using the following:

DiffRunner.Kill(file1, file2);

snippet source | anchor

Note that this method will respect the above difference behavior in terms of MDI behavior.

File type detection

DiffEngine use EmptyFiles to determine if a given file or extension is a binary or text. Custom extensions can be added, or existing ones changed.

BuildServerDetector

BuildServerDetector.Detected returns true if the current code is running on a build/CI server.

Supports:

  • AppVeyor
  • Travis
  • Jenkins
  • GitHub Actions
  • AzureDevops
  • TeamCity
  • MyGet
  • GitLab
  • GoCD
  • Bitbucket Pipelines

There are also individual properties to check for each specific build system

var isWsl = BuildServerDetector.IsWsl;
var isTravis = BuildServerDetector.IsTravis;
var isJenkins = BuildServerDetector.IsJenkins;
var isGithubAction = BuildServerDetector.IsGithubAction;
var isAzureDevops = BuildServerDetector.IsAzureDevops;
var isTeamCity = BuildServerDetector.IsTeamCity;
var isGitLab = BuildServerDetector.IsGitLab;
var isMyGet = BuildServerDetector.IsMyGet;
var isGoDc = BuildServerDetector.IsGoDc;
var isDocker = BuildServerDetector.IsDocker;
var isAppVeyor = BuildServerDetector.IsAppVeyor;
var isBitbucketPipelines = BuildServerDetector.IsBitbucketPipelines;

snippet source | anchor

WSL

Running under WSL is not treated as a build server, since a WSL session is usually a developer machine. BuildServerDetector.IsWsl reports it, and BuildServerDetector.Detected ignores it. Diff tools are launched there, the ones installed on Windows included: see Windows Subsystem for Linux.

A build that runs its tests inside WSL from a Windows build agent is the case to watch. The variables the build server sets exist on the Windows side, and WSL only passes across the ones named in WSLENV. So inside WSL nothing is detected, and diff tools are launched on the build agent.

To have such a build detected, either name the build server's variable in WSLENV on the Windows side, for example on Azure DevOps:

set WSLENV=TF_BUILD:%WSLENV%

or set one of the detected variables on the command that starts the tests:

wsl -- env TF_BUILD=True dotnet test

To treat every WSL run as a build server, in a test:

BuildServerDetector.Detected = BuildServerDetector.Detected || BuildServerDetector.IsWsl;

That value is scoped to the current async context, as described below.

Override in tests

BuildServerDetector.Detected can be set at test time. The value is stored in an AsyncLocal, so it is scoped to the current async context and does not leak to other threads or tests running in parallel.

[Test]
public async Task SetDetectedPersistsInAsyncContext()
{
    var original = BuildServerDetector.Detected;
    try
    {
        BuildServerDetector.Detected = true;
        await Assert.That(BuildServerDetector.Detected).IsTrue();

        await Task.Delay(1);

        await Assert.That(BuildServerDetector.Detected).IsTrue();
    }
    finally
    {
        BuildServerDetector.Detected = original;
    }
}

[Test]
public async Task SetDetectedDoesNotLeakToOtherContexts()
{
    var parentValue = BuildServerDetector.Detected;

    await Task.Run(async () =>
    {
        BuildServerDetector.Detected = true;
        await Assert.That(BuildServerDetector.Detected).IsTrue();
    });

    await Assert.That(BuildServerDetector.Detected).IsEqualTo(parentValue);
}

snippet source | anchor

Automatic AI detection

DiffEngine automatically detects when it is running inside an AI-powered CLI environment and disables the diff tool launch. This means no DiffEngine_Disabled=true environment variable is required when running tests from within an AI CLI — it is detected and handled automatically.

Supported AI CLIs:

  • GitHub Copilot CLI
  • Aider
  • Claude Code

Programmatic usage

AiCliDetector.Detected returns true if the current code is running in an AI-powered CLI environment.

There are also individual properties to check for each specific AI CLI

var isCopilot = AiCliDetector.IsCopilot;
var isCursor = AiCliDetector.IsCursor;
var isAider = AiCliDetector.IsAider;
var isClaudeCode = AiCliDetector.IsClaudeCode;
var isGeminiCli = AiCliDetector.IsGeminiCli;
var isCodex = AiCliDetector.IsCodex;
var isAmazonQ = AiCliDetector.IsAmazonQ;
var isOpenCode = AiCliDetector.IsOpenCode;
var isCline = AiCliDetector.IsCline;
var isAugment = AiCliDetector.IsAugment;
var isTraeAi = AiCliDetector.IsTraeAi;
var isGoose = AiCliDetector.IsGoose;
var isAmp = AiCliDetector.IsAmp;

snippet source | anchor

Disable for a machine/process

Set an environment variable DiffEngine_Disabled with the value true.

Disable in code

DiffRunner.Disabled = true;

Disable the tray

Pending moves and deletes are sent to DiffEngineTray when one is running. That tracking is separate from launching a diff tool, so disabling diff does not stop it.

Set an environment variable DiffEngine_TrayDisabled with the value true, or in code:

DiffRunner.TrayDisabled = true;

More detail.

Icons

Game designed by Andrejs Kirma from The Noun Project.

Tray icons from LineIcons.

About

Manages launching and cleanup of diff tools

Resources

Readme
MIT license

Code of conduct

Code of conduct
Activity
Custom properties

Stars

240 stars

Watchers

4 watching

Forks

32 forks
Report repository

Releases

Sponsor this project

Used by

Contributors

Languages

You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.