*.{md,cs}: remove CR line endings

Re-standardize on LF thoughout the repository, following on
from commit 6a8a91fb83.
This commit is contained in:
Chris Darroch 2020-09-17 21:53:00 -07:00 коммит произвёл Chris Darroch
Родитель 02890e3f85
Коммит 64a8fd72fe
27 изменённых файлов: 931 добавлений и 931 удалений

Просмотреть файл

@ -1,37 +1,37 @@
## Security
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
This information will help us triage your report more quickly.
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
## Preferred Languages
We prefer all communications to be in English.
## Policy
## Security
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue
This information will help us triage your report more quickly.
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
## Preferred Languages
We prefer all communications to be in English.
## Policy
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).

Просмотреть файл

@ -1,4 +1,4 @@
using Scalar.Common.Git;
using Scalar.Common.Git;
using Scalar.Common.Tracing;
using System;
using System.Collections.Generic;

Просмотреть файл

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
namespace Scalar.Common.RepoRegistry

Просмотреть файл

@ -33,13 +33,13 @@ namespace Scalar.Tests
return this.args.Remove(arg);
}
public void AddGlobalSetupIfNeeded(string globalSetup)
{
// If there are any test filters, the GlobalSetup still needs to run so add it.
if (this.args.Any(x => x.StartsWith("--test=")))
{
this.args.Add($"--test={globalSetup}");
}
public void AddGlobalSetupIfNeeded(string globalSetup)
{
// If there are any test filters, the GlobalSetup still needs to run so add it.
if (this.args.Any(x => x.StartsWith("--test=")))
{
this.args.Add($"--test={globalSetup}");
}
}
public int RunTests(ICollection<string> includeCategories, ICollection<string> excludeCategories)

Просмотреть файл

@ -1,4 +1,4 @@
using NUnit.Framework;
using NUnit.Framework;
using Scalar.FunctionalTests.FileSystemRunners;
using Scalar.FunctionalTests.Tools;
using Scalar.Tests.Should;

Просмотреть файл

@ -1,4 +1,4 @@
using NUnit.Framework;
using NUnit.Framework;
using Scalar.FunctionalTests.FileSystemRunners;
using Scalar.FunctionalTests.Should;
using Scalar.FunctionalTests.Tools;

Просмотреть файл

@ -81,7 +81,7 @@ namespace Scalar.FunctionalTests.Tests.EnlistmentPerFixture
bool timerScheduled = false;
// Service starts upgrade checks after 60 seconds.
// Service starts upgrade checks after 60 seconds.
Thread.Sleep(TimeSpan.FromSeconds(60));
for (int trialCount = 0; trialCount < 30; trialCount++)
{

Просмотреть файл

@ -1,4 +1,4 @@
using NUnit.Framework;
using NUnit.Framework;
using Scalar.Tests.Should;
namespace Scalar.FunctionalTests.Tests.GitRepoPerFixture

Просмотреть файл

@ -1,4 +1,4 @@
using NUnit.Framework;
using NUnit.Framework;
using Scalar.FunctionalTests.Tools;
namespace Scalar.FunctionalTests.Tests.GitRepoPerFixture

Просмотреть файл

@ -1,4 +1,4 @@
using System;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;

Просмотреть файл

@ -2,16 +2,16 @@ using System.Xml.Serialization;
namespace Scalar.Service.UI.Data
{
[XmlRoot("action")]
public class ActionItem
{
[XmlAttribute("content")]
public string Content { get; set; }
[XmlAttribute("arguments")]
public string Arguments { get; set; }
[XmlAttribute("activationtype")]
public string ActivationType { get; set; }
[XmlRoot("action")]
public class ActionItem
{
[XmlAttribute("content")]
public string Content { get; set; }
[XmlAttribute("arguments")]
public string Arguments { get; set; }
[XmlAttribute("activationtype")]
public string ActivationType { get; set; }
}
}

Просмотреть файл

@ -1,10 +1,10 @@
using System;
namespace Scalar.Service.UI
{
public interface IToastNotifier
{
Action<string> UserResponseCallback { get; set; }
void Notify(string title, string message, string actionButtonTitle, string callbackArgs);
}
}
using System;
namespace Scalar.Service.UI
{
public interface IToastNotifier
{
Action<string> UserResponseCallback { get; set; }
void Notify(string title, string message, string actionButtonTitle, string callbackArgs);
}
}

Просмотреть файл

@ -14,42 +14,42 @@ using XmlDocument = Windows.Data.Xml.Dom.XmlDocument;
namespace Scalar.Service.UI
{
public static class Program
{
public static void Main(string[] args)
{
ScalarPlatformLoader.Initialize();
using (JsonTracer tracer = new JsonTracer("Microsoft.Git.GVFS.Service.UI", "Service.UI"))
{
string error;
string serviceUILogDirectory = ScalarPlatform.Instance.GetLogsDirectoryForGVFSComponent(ScalarConstants.Service.UIName);
if (!ScalarPlatform.Instance.FileSystem.TryCreateDirectoryWithAdminAndUserModifyPermissions(serviceUILogDirectory, out error))
{
EventMetadata metadata = new EventMetadata();
metadata.Add(nameof(serviceUILogDirectory), serviceUILogDirectory);
metadata.Add(nameof(error), error);
tracer.RelatedWarning(
metadata,
"Failed to create service UI logs directory",
Keywords.Telemetry);
}
else
{
string logFilePath = ScalarEnlistment.GetNewScalarLogFileName(
serviceUILogDirectory,
ScalarConstants.LogFileTypes.ServiceUI,
logId: Environment.UserName);
tracer.AddLogFileEventListener(logFilePath, EventLevel.Informational, Keywords.Any);
}
WinToastNotifier winToastNotifier = new WinToastNotifier(tracer);
ScalarToastRequestHandler toastRequestHandler = new ScalarToastRequestHandler(winToastNotifier, tracer);
GVFSServiceUI process = new GVFSServiceUI(tracer, toastRequestHandler);
process.Start(args);
}
}
public static class Program
{
public static void Main(string[] args)
{
ScalarPlatformLoader.Initialize();
using (JsonTracer tracer = new JsonTracer("Microsoft.Git.GVFS.Service.UI", "Service.UI"))
{
string error;
string serviceUILogDirectory = ScalarPlatform.Instance.GetLogsDirectoryForGVFSComponent(ScalarConstants.Service.UIName);
if (!ScalarPlatform.Instance.FileSystem.TryCreateDirectoryWithAdminAndUserModifyPermissions(serviceUILogDirectory, out error))
{
EventMetadata metadata = new EventMetadata();
metadata.Add(nameof(serviceUILogDirectory), serviceUILogDirectory);
metadata.Add(nameof(error), error);
tracer.RelatedWarning(
metadata,
"Failed to create service UI logs directory",
Keywords.Telemetry);
}
else
{
string logFilePath = ScalarEnlistment.GetNewScalarLogFileName(
serviceUILogDirectory,
ScalarConstants.LogFileTypes.ServiceUI,
logId: Environment.UserName);
tracer.AddLogFileEventListener(logFilePath, EventLevel.Informational, Keywords.Any);
}
WinToastNotifier winToastNotifier = new WinToastNotifier(tracer);
ScalarToastRequestHandler toastRequestHandler = new ScalarToastRequestHandler(winToastNotifier, tracer);
GVFSServiceUI process = new GVFSServiceUI(tracer, toastRequestHandler);
process.Start(args);
}
}
}
}

Просмотреть файл

@ -1,61 +1,61 @@
using Scalar.Common;
using Scalar.Common.NamedPipes;
using Scalar.Common.Tracing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Scalar.Service.UI
{
public class GVFSServiceUI
{
private readonly ITracer tracer;
private readonly ScalarToastRequestHandler toastRequestHandler;
public GVFSServiceUI(ITracer tracer, ScalarToastRequestHandler toastRequestHandler)
{
this.tracer = tracer;
this.toastRequestHandler = toastRequestHandler;
}
public void Start(string[] args)
{
using (ITracer activity = this.tracer.StartActivity("Start", EventLevel.Informational))
using (NamedPipeServer server = NamedPipeServer.StartNewServer(ScalarConstants.Service.UIName, this.tracer, this.HandleRequest))
{
ManualResetEvent mre = new ManualResetEvent(false);
mre.WaitOne();
}
}
private void HandleRequest(ITracer tracer, string request, NamedPipeServer.Connection connection)
{
try
{
NamedPipeMessages.Message message = NamedPipeMessages.Message.FromString(request);
switch (message.Header)
{
case NamedPipeMessages.Notification.Request.Header:
NamedPipeMessages.Notification.Request toastRequest = NamedPipeMessages.Notification.Request.FromMessage(message);
if (toastRequest != null)
{
using (ITracer activity = this.tracer.StartActivity("SendToast", EventLevel.Informational))
{
this.toastRequestHandler.HandleToastRequest(activity, toastRequest);
}
}
break;
}
}
catch (Exception e)
{
this.tracer.RelatedError("Unhandled exception: {0}", e.ToString());
}
}
}
}
using Scalar.Common;
using Scalar.Common.NamedPipes;
using Scalar.Common.Tracing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Scalar.Service.UI
{
public class GVFSServiceUI
{
private readonly ITracer tracer;
private readonly ScalarToastRequestHandler toastRequestHandler;
public GVFSServiceUI(ITracer tracer, ScalarToastRequestHandler toastRequestHandler)
{
this.tracer = tracer;
this.toastRequestHandler = toastRequestHandler;
}
public void Start(string[] args)
{
using (ITracer activity = this.tracer.StartActivity("Start", EventLevel.Informational))
using (NamedPipeServer server = NamedPipeServer.StartNewServer(ScalarConstants.Service.UIName, this.tracer, this.HandleRequest))
{
ManualResetEvent mre = new ManualResetEvent(false);
mre.WaitOne();
}
}
private void HandleRequest(ITracer tracer, string request, NamedPipeServer.Connection connection)
{
try
{
NamedPipeMessages.Message message = NamedPipeMessages.Message.FromString(request);
switch (message.Header)
{
case NamedPipeMessages.Notification.Request.Header:
NamedPipeMessages.Notification.Request toastRequest = NamedPipeMessages.Notification.Request.FromMessage(message);
if (toastRequest != null)
{
using (ITracer activity = this.tracer.StartActivity("SendToast", EventLevel.Informational))
{
this.toastRequestHandler.HandleToastRequest(activity, toastRequest);
}
}
break;
}
}
catch (Exception e)
{
this.tracer.RelatedError("Unhandled exception: {0}", e.ToString());
}
}
}
}

Просмотреть файл

@ -1,103 +1,103 @@
using Scalar.Common;
using Scalar.Common.Tracing;
using Scalar.Service.UI.Data;
using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Windows.UI.Notifications;
using XmlDocument = Windows.Data.Xml.Dom.XmlDocument;
namespace Scalar.Service.UI
{
public class WinToastNotifier : IToastNotifier
{
private const string ServiceAppId = "Scalar";
private const string ScalarIconName = "scalar.ico";
private ITracer tracer;
public WinToastNotifier(ITracer tracer)
{
this.tracer = tracer;
}
public Action<string> UserResponseCallback { get; set; }
public void Notify(string title, string message, string actionButtonTitle, string callbackArgs)
{
// Reference: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts
ToastData toastData = new ToastData();
toastData.Visual = new VisualData();
BindingData binding = new BindingData();
toastData.Visual.Binding = binding;
// ToastGeneric- Our toast contains VFSForGit icon and text
binding.Template = "ToastGeneric";
binding.Items = new XmlList<BindingItem>();
binding.Items.Add(new BindingItem.TextData(title));
binding.Items.Add(new BindingItem.TextData(message));
string logo = "file:///" + Path.Combine(ProcessHelper.GetCurrentProcessLocation(), ScalarIconName);
binding.Items.Add(new BindingItem.ImageData()
{
Source = logo,
Placement = "appLogoOverride",
HintCrop = "circle"
});
if (!string.IsNullOrEmpty(actionButtonTitle))
{
ActionsData actionsData = new ActionsData();
actionsData.Actions = new XmlList<ActionItem>();
actionsData.Actions.Add(new ActionItem()
{
Content = actionButtonTitle,
Arguments = string.IsNullOrEmpty(callbackArgs) ? string.Empty : callbackArgs,
ActivationType = "background"
});
toastData.Actions = actionsData;
}
XmlDocument toastXml = new XmlDocument();
using (StringWriter stringWriter = new StringWriter())
using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { OmitXmlDeclaration = true }))
{
XmlSerializer serializer = new XmlSerializer(toastData.GetType());
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
serializer.Serialize(xmlWriter, toastData, namespaces);
toastXml.LoadXml(stringWriter.ToString());
}
ToastNotification toastNotification = new ToastNotification(toastXml);
toastNotification.Activated += this.ToastActivated;
toastNotification.Dismissed += this.ToastDismissed;
toastNotification.Failed += this.ToastFailed;
ToastNotifier toastNotifier = ToastNotificationManager.CreateToastNotifier(ServiceAppId);
toastNotifier.Show(toastNotification);
}
private void ToastActivated(ToastNotification sender, object e)
{
ToastActivatedEventArgs args = (ToastActivatedEventArgs)e;
this.UserResponseCallback?.Invoke(args.Arguments);
}
private void ToastDismissed(ToastNotification sender, ToastDismissedEventArgs e)
{
this.tracer.RelatedInfo($"{nameof(this.ToastDismissed)}: {e.Reason}");
}
private void ToastFailed(ToastNotification sender, ToastFailedEventArgs e)
{
this.tracer.RelatedInfo($"{nameof(this.ToastFailed)}: {e.ErrorCode.ToString()}");
}
}
}
using Scalar.Common;
using Scalar.Common.Tracing;
using Scalar.Service.UI.Data;
using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;
using Windows.UI.Notifications;
using XmlDocument = Windows.Data.Xml.Dom.XmlDocument;
namespace Scalar.Service.UI
{
public class WinToastNotifier : IToastNotifier
{
private const string ServiceAppId = "Scalar";
private const string ScalarIconName = "scalar.ico";
private ITracer tracer;
public WinToastNotifier(ITracer tracer)
{
this.tracer = tracer;
}
public Action<string> UserResponseCallback { get; set; }
public void Notify(string title, string message, string actionButtonTitle, string callbackArgs)
{
// Reference: https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/adaptive-interactive-toasts
ToastData toastData = new ToastData();
toastData.Visual = new VisualData();
BindingData binding = new BindingData();
toastData.Visual.Binding = binding;
// ToastGeneric- Our toast contains VFSForGit icon and text
binding.Template = "ToastGeneric";
binding.Items = new XmlList<BindingItem>();
binding.Items.Add(new BindingItem.TextData(title));
binding.Items.Add(new BindingItem.TextData(message));
string logo = "file:///" + Path.Combine(ProcessHelper.GetCurrentProcessLocation(), ScalarIconName);
binding.Items.Add(new BindingItem.ImageData()
{
Source = logo,
Placement = "appLogoOverride",
HintCrop = "circle"
});
if (!string.IsNullOrEmpty(actionButtonTitle))
{
ActionsData actionsData = new ActionsData();
actionsData.Actions = new XmlList<ActionItem>();
actionsData.Actions.Add(new ActionItem()
{
Content = actionButtonTitle,
Arguments = string.IsNullOrEmpty(callbackArgs) ? string.Empty : callbackArgs,
ActivationType = "background"
});
toastData.Actions = actionsData;
}
XmlDocument toastXml = new XmlDocument();
using (StringWriter stringWriter = new StringWriter())
using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter, new XmlWriterSettings { OmitXmlDeclaration = true }))
{
XmlSerializer serializer = new XmlSerializer(toastData.GetType());
XmlSerializerNamespaces namespaces = new XmlSerializerNamespaces();
namespaces.Add(string.Empty, string.Empty);
serializer.Serialize(xmlWriter, toastData, namespaces);
toastXml.LoadXml(stringWriter.ToString());
}
ToastNotification toastNotification = new ToastNotification(toastXml);
toastNotification.Activated += this.ToastActivated;
toastNotification.Dismissed += this.ToastDismissed;
toastNotification.Failed += this.ToastFailed;
ToastNotifier toastNotifier = ToastNotificationManager.CreateToastNotifier(ServiceAppId);
toastNotifier.Show(toastNotification);
}
private void ToastActivated(ToastNotification sender, object e)
{
ToastActivatedEventArgs args = (ToastActivatedEventArgs)e;
this.UserResponseCallback?.Invoke(args.Arguments);
}
private void ToastDismissed(ToastNotification sender, ToastDismissedEventArgs e)
{
this.tracer.RelatedInfo($"{nameof(this.ToastDismissed)}: {e.Reason}");
}
private void ToastFailed(ToastNotification sender, ToastFailedEventArgs e)
{
this.tracer.RelatedInfo($"{nameof(this.ToastFailed)}: {e.ErrorCode.ToString()}");
}
}
}

Просмотреть файл

@ -28,9 +28,9 @@ namespace Scalar.Service
{
if (!ScalarEnlistment.IsUnattended(this.tracer))
{
// Adding 60 seconds wait time here. This gives VFSForGit installer/upgrader
// sufficient enough time to launch GVFS.Service.UI that is needed to display
// Upgrade available toaster.
// Adding 60 seconds wait time here. This gives VFSForGit installer/upgrader
// sufficient enough time to launch GVFS.Service.UI that is needed to display
// Upgrade available toaster.
TimeSpan startTime = TimeSpan.FromSeconds(60);
this.tracer.RelatedInfo("Starting auto upgrade checks.");
@ -193,13 +193,13 @@ namespace Scalar.Service
return true;
}
private void DisplayUpgradeAvailableToast(string version)
{
NamedPipeMessages.Notification.Request request = new NamedPipeMessages.Notification.Request();
request.Id = NamedPipeMessages.Notification.Request.Identifier.UpgradeAvailable;
request.NewVersion = version;
this.notificationHandler.SendNotification(request);
private void DisplayUpgradeAvailableToast(string version)
{
NamedPipeMessages.Notification.Request request = new NamedPipeMessages.Notification.Request();
request.Id = NamedPipeMessages.Notification.Request.Identifier.UpgradeAvailable;
request.NewVersion = version;
this.notificationHandler.SendNotification(request);
}
}
}

Просмотреть файл

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Concurrent;
using System.Threading;
using Scalar.Common.Tracing;

Просмотреть файл

@ -1,6 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NUnit.Framework;
using Scalar.Common;

Просмотреть файл

@ -1,75 +1,75 @@
using Moq;
using Moq;
using NUnit.Framework;
using Scalar.Common.NamedPipes;
using Scalar.Service.UI;
using Scalar.UnitTests.Mock.Common;
using System;
namespace Scalar.UnitTests.Windows.ServiceUI
{
[TestFixture]
public class ScalarToastRequestHandlerTests
{
private NamedPipeMessages.Notification.Request request;
private ScalarToastRequestHandler toastHandler;
private Mock<IToastNotifier> mockToastNotifier;
private MockTracer tracer;
[SetUp]
public void Setup()
{
this.tracer = new MockTracer();
this.mockToastNotifier = new Mock<IToastNotifier>(MockBehavior.Strict);
this.mockToastNotifier.SetupSet(toastNotifier => toastNotifier.UserResponseCallback = It.IsAny<Action<string>>()).Verifiable();
this.toastHandler = new ScalarToastRequestHandler(this.mockToastNotifier.Object, this.tracer);
this.request = new NamedPipeMessages.Notification.Request();
}
[TestCase]
public void UpgradeToastIsActionableAndContainsVersionInfo()
{
const string version = "1.0.956749.2";
this.request.Id = NamedPipeMessages.Notification.Request.Identifier.UpgradeAvailable;
this.request.NewVersion = version;
this.VerifyToastMessage(
expectedTitle: "New version " + version + " is available",
expectedMessage: "click Upgrade button",
expectedButtonTitle: "Upgrade",
expectedScalarCmd: "scalar upgrade --confirm");
}
[TestCase]
public void UnknownToastRequestGetsIgnored()
{
this.request.Id = (NamedPipeMessages.Notification.Request.Identifier)10;
this.toastHandler.HandleToastRequest(this.tracer, this.request);
this.mockToastNotifier.Verify(
toastNotifier => toastNotifier.Notify(
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>()),
Times.Never());
}
private void VerifyToastMessage(
string expectedTitle,
string expectedMessage,
string expectedButtonTitle,
string expectedScalarCmd)
{
this.mockToastNotifier.Setup(toastNotifier => toastNotifier.Notify(
expectedTitle,
It.Is<string>(message => message.Contains(expectedMessage)),
expectedButtonTitle,
expectedScalarCmd));
this.toastHandler.HandleToastRequest(this.tracer, this.request);
this.mockToastNotifier.VerifyAll();
}
}
}
using Scalar.Common.NamedPipes;
using Scalar.Service.UI;
using Scalar.UnitTests.Mock.Common;
using System;
namespace Scalar.UnitTests.Windows.ServiceUI
{
[TestFixture]
public class ScalarToastRequestHandlerTests
{
private NamedPipeMessages.Notification.Request request;
private ScalarToastRequestHandler toastHandler;
private Mock<IToastNotifier> mockToastNotifier;
private MockTracer tracer;
[SetUp]
public void Setup()
{
this.tracer = new MockTracer();
this.mockToastNotifier = new Mock<IToastNotifier>(MockBehavior.Strict);
this.mockToastNotifier.SetupSet(toastNotifier => toastNotifier.UserResponseCallback = It.IsAny<Action<string>>()).Verifiable();
this.toastHandler = new ScalarToastRequestHandler(this.mockToastNotifier.Object, this.tracer);
this.request = new NamedPipeMessages.Notification.Request();
}
[TestCase]
public void UpgradeToastIsActionableAndContainsVersionInfo()
{
const string version = "1.0.956749.2";
this.request.Id = NamedPipeMessages.Notification.Request.Identifier.UpgradeAvailable;
this.request.NewVersion = version;
this.VerifyToastMessage(
expectedTitle: "New version " + version + " is available",
expectedMessage: "click Upgrade button",
expectedButtonTitle: "Upgrade",
expectedScalarCmd: "scalar upgrade --confirm");
}
[TestCase]
public void UnknownToastRequestGetsIgnored()
{
this.request.Id = (NamedPipeMessages.Notification.Request.Identifier)10;
this.toastHandler.HandleToastRequest(this.tracer, this.request);
this.mockToastNotifier.Verify(
toastNotifier => toastNotifier.Notify(
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>()),
Times.Never());
}
private void VerifyToastMessage(
string expectedTitle,
string expectedMessage,
string expectedButtonTitle,
string expectedScalarCmd)
{
this.mockToastNotifier.Setup(toastNotifier => toastNotifier.Notify(
expectedTitle,
It.Is<string>(message => message.Contains(expectedMessage)),
expectedButtonTitle,
expectedScalarCmd));
this.toastHandler.HandleToastRequest(this.tracer, this.request);
this.mockToastNotifier.VerifyAll();
}
}
}

Просмотреть файл

@ -1,99 +1,99 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30406.18
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar", "Scalar\Scalar.csproj", "{31208ED8-5B83-4BE6-802A-18EE67434537}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Common", "Scalar.Common\Scalar.Common.csproj", "{179EAE33-265B-4698-BBC7-130F28F6D768}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Service", "Scalar.Service\Scalar.Service.csproj", "{E75C4E5C-4446-43A3-BDE0-C9C4297485FA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Upgrader", "Scalar.Upgrader\Scalar.Upgrader.csproj", "{424D0102-50EE-4CA6-A937-C8A89CE10103}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.UnitTests", "Scalar.UnitTests\Scalar.UnitTests.csproj", "{B1D1E8BE-D633-4624-A821-B222EB1B8020}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EB9427BB-456A-4319-8916-E782E0F5F6D3}"
ProjectSection(SolutionItems) = preProject
Dependencies.props = Dependencies.props
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
global.json = global.json
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.FunctionalTests", "Scalar.FunctionalTests\Scalar.FunctionalTests.csproj", "{C7E08779-6F45-4025-89E1-31346C9B234F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.TestInfrastructure", "Scalar.TestInfrastructure\Scalar.TestInfrastructure.csproj", "{77FC445D-FD03-4EE0-8582-7BD1437D9842}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.MSBuild", "Scalar.MSBuild\Scalar.MSBuild.csproj", "{6B05E1DE-1C67-48F7-9A2A-E109D7252CF2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Installer.Mac", "Scalar.Installer.Mac\Scalar.Installer.Mac.csproj", "{5CFE04A9-F65A-4EEF-B237-7608D19A87DE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Installer.Windows", "Scalar.Installer.Windows\Scalar.Installer.Windows.csproj", "{913C7CBD-876C-45D8-B59E-D0849CD219E4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Service.UI", "Scalar.Service.UI\Scalar.Service.UI.csproj", "{32D8335E-E9E8-4AD8-BAE5-162F53AA4D72}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Notifications.Mac", "Scalar.Notifications.Mac\Scalar.Notifications.Mac.csproj", "{ED367118-BFB1-41CA-A010-E46C28796ED8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{31208ED8-5B83-4BE6-802A-18EE67434537}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{31208ED8-5B83-4BE6-802A-18EE67434537}.Debug|Any CPU.Build.0 = Debug|Any CPU
{31208ED8-5B83-4BE6-802A-18EE67434537}.Release|Any CPU.ActiveCfg = Release|Any CPU
{31208ED8-5B83-4BE6-802A-18EE67434537}.Release|Any CPU.Build.0 = Release|Any CPU
{179EAE33-265B-4698-BBC7-130F28F6D768}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{179EAE33-265B-4698-BBC7-130F28F6D768}.Debug|Any CPU.Build.0 = Debug|Any CPU
{179EAE33-265B-4698-BBC7-130F28F6D768}.Release|Any CPU.ActiveCfg = Release|Any CPU
{179EAE33-265B-4698-BBC7-130F28F6D768}.Release|Any CPU.Build.0 = Release|Any CPU
{E75C4E5C-4446-43A3-BDE0-C9C4297485FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E75C4E5C-4446-43A3-BDE0-C9C4297485FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E75C4E5C-4446-43A3-BDE0-C9C4297485FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E75C4E5C-4446-43A3-BDE0-C9C4297485FA}.Release|Any CPU.Build.0 = Release|Any CPU
{424D0102-50EE-4CA6-A937-C8A89CE10103}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{424D0102-50EE-4CA6-A937-C8A89CE10103}.Debug|Any CPU.Build.0 = Debug|Any CPU
{424D0102-50EE-4CA6-A937-C8A89CE10103}.Release|Any CPU.ActiveCfg = Release|Any CPU
{424D0102-50EE-4CA6-A937-C8A89CE10103}.Release|Any CPU.Build.0 = Release|Any CPU
{B1D1E8BE-D633-4624-A821-B222EB1B8020}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B1D1E8BE-D633-4624-A821-B222EB1B8020}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B1D1E8BE-D633-4624-A821-B222EB1B8020}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B1D1E8BE-D633-4624-A821-B222EB1B8020}.Release|Any CPU.Build.0 = Release|Any CPU
{C7E08779-6F45-4025-89E1-31346C9B234F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C7E08779-6F45-4025-89E1-31346C9B234F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C7E08779-6F45-4025-89E1-31346C9B234F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C7E08779-6F45-4025-89E1-31346C9B234F}.Release|Any CPU.Build.0 = Release|Any CPU
{77FC445D-FD03-4EE0-8582-7BD1437D9842}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77FC445D-FD03-4EE0-8582-7BD1437D9842}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77FC445D-FD03-4EE0-8582-7BD1437D9842}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77FC445D-FD03-4EE0-8582-7BD1437D9842}.Release|Any CPU.Build.0 = Release|Any CPU
{6B05E1DE-1C67-48F7-9A2A-E109D7252CF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B05E1DE-1C67-48F7-9A2A-E109D7252CF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B05E1DE-1C67-48F7-9A2A-E109D7252CF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B05E1DE-1C67-48F7-9A2A-E109D7252CF2}.Release|Any CPU.Build.0 = Release|Any CPU
{5CFE04A9-F65A-4EEF-B237-7608D19A87DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5CFE04A9-F65A-4EEF-B237-7608D19A87DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5CFE04A9-F65A-4EEF-B237-7608D19A87DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5CFE04A9-F65A-4EEF-B237-7608D19A87DE}.Release|Any CPU.Build.0 = Release|Any CPU
{913C7CBD-876C-45D8-B59E-D0849CD219E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{913C7CBD-876C-45D8-B59E-D0849CD219E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{913C7CBD-876C-45D8-B59E-D0849CD219E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{913C7CBD-876C-45D8-B59E-D0849CD219E4}.Release|Any CPU.Build.0 = Release|Any CPU
{32D8335E-E9E8-4AD8-BAE5-162F53AA4D72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{32D8335E-E9E8-4AD8-BAE5-162F53AA4D72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{32D8335E-E9E8-4AD8-BAE5-162F53AA4D72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{32D8335E-E9E8-4AD8-BAE5-162F53AA4D72}.Release|Any CPU.Build.0 = Release|Any CPU
{ED367118-BFB1-41CA-A010-E46C28796ED8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED367118-BFB1-41CA-A010-E46C28796ED8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED367118-BFB1-41CA-A010-E46C28796ED8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED367118-BFB1-41CA-A010-E46C28796ED8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FDE61E04-DC84-437F-A176-40CD62CDE05F}
EndGlobalSection
EndGlobal

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30406.18
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar", "Scalar\Scalar.csproj", "{31208ED8-5B83-4BE6-802A-18EE67434537}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Common", "Scalar.Common\Scalar.Common.csproj", "{179EAE33-265B-4698-BBC7-130F28F6D768}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Service", "Scalar.Service\Scalar.Service.csproj", "{E75C4E5C-4446-43A3-BDE0-C9C4297485FA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Upgrader", "Scalar.Upgrader\Scalar.Upgrader.csproj", "{424D0102-50EE-4CA6-A937-C8A89CE10103}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.UnitTests", "Scalar.UnitTests\Scalar.UnitTests.csproj", "{B1D1E8BE-D633-4624-A821-B222EB1B8020}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EB9427BB-456A-4319-8916-E782E0F5F6D3}"
ProjectSection(SolutionItems) = preProject
Dependencies.props = Dependencies.props
Directory.Build.props = Directory.Build.props
Directory.Build.targets = Directory.Build.targets
global.json = global.json
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.FunctionalTests", "Scalar.FunctionalTests\Scalar.FunctionalTests.csproj", "{C7E08779-6F45-4025-89E1-31346C9B234F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.TestInfrastructure", "Scalar.TestInfrastructure\Scalar.TestInfrastructure.csproj", "{77FC445D-FD03-4EE0-8582-7BD1437D9842}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.MSBuild", "Scalar.MSBuild\Scalar.MSBuild.csproj", "{6B05E1DE-1C67-48F7-9A2A-E109D7252CF2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Installer.Mac", "Scalar.Installer.Mac\Scalar.Installer.Mac.csproj", "{5CFE04A9-F65A-4EEF-B237-7608D19A87DE}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Installer.Windows", "Scalar.Installer.Windows\Scalar.Installer.Windows.csproj", "{913C7CBD-876C-45D8-B59E-D0849CD219E4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Service.UI", "Scalar.Service.UI\Scalar.Service.UI.csproj", "{32D8335E-E9E8-4AD8-BAE5-162F53AA4D72}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scalar.Notifications.Mac", "Scalar.Notifications.Mac\Scalar.Notifications.Mac.csproj", "{ED367118-BFB1-41CA-A010-E46C28796ED8}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{31208ED8-5B83-4BE6-802A-18EE67434537}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{31208ED8-5B83-4BE6-802A-18EE67434537}.Debug|Any CPU.Build.0 = Debug|Any CPU
{31208ED8-5B83-4BE6-802A-18EE67434537}.Release|Any CPU.ActiveCfg = Release|Any CPU
{31208ED8-5B83-4BE6-802A-18EE67434537}.Release|Any CPU.Build.0 = Release|Any CPU
{179EAE33-265B-4698-BBC7-130F28F6D768}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{179EAE33-265B-4698-BBC7-130F28F6D768}.Debug|Any CPU.Build.0 = Debug|Any CPU
{179EAE33-265B-4698-BBC7-130F28F6D768}.Release|Any CPU.ActiveCfg = Release|Any CPU
{179EAE33-265B-4698-BBC7-130F28F6D768}.Release|Any CPU.Build.0 = Release|Any CPU
{E75C4E5C-4446-43A3-BDE0-C9C4297485FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E75C4E5C-4446-43A3-BDE0-C9C4297485FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E75C4E5C-4446-43A3-BDE0-C9C4297485FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E75C4E5C-4446-43A3-BDE0-C9C4297485FA}.Release|Any CPU.Build.0 = Release|Any CPU
{424D0102-50EE-4CA6-A937-C8A89CE10103}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{424D0102-50EE-4CA6-A937-C8A89CE10103}.Debug|Any CPU.Build.0 = Debug|Any CPU
{424D0102-50EE-4CA6-A937-C8A89CE10103}.Release|Any CPU.ActiveCfg = Release|Any CPU
{424D0102-50EE-4CA6-A937-C8A89CE10103}.Release|Any CPU.Build.0 = Release|Any CPU
{B1D1E8BE-D633-4624-A821-B222EB1B8020}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B1D1E8BE-D633-4624-A821-B222EB1B8020}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B1D1E8BE-D633-4624-A821-B222EB1B8020}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B1D1E8BE-D633-4624-A821-B222EB1B8020}.Release|Any CPU.Build.0 = Release|Any CPU
{C7E08779-6F45-4025-89E1-31346C9B234F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C7E08779-6F45-4025-89E1-31346C9B234F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C7E08779-6F45-4025-89E1-31346C9B234F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C7E08779-6F45-4025-89E1-31346C9B234F}.Release|Any CPU.Build.0 = Release|Any CPU
{77FC445D-FD03-4EE0-8582-7BD1437D9842}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{77FC445D-FD03-4EE0-8582-7BD1437D9842}.Debug|Any CPU.Build.0 = Debug|Any CPU
{77FC445D-FD03-4EE0-8582-7BD1437D9842}.Release|Any CPU.ActiveCfg = Release|Any CPU
{77FC445D-FD03-4EE0-8582-7BD1437D9842}.Release|Any CPU.Build.0 = Release|Any CPU
{6B05E1DE-1C67-48F7-9A2A-E109D7252CF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6B05E1DE-1C67-48F7-9A2A-E109D7252CF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6B05E1DE-1C67-48F7-9A2A-E109D7252CF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6B05E1DE-1C67-48F7-9A2A-E109D7252CF2}.Release|Any CPU.Build.0 = Release|Any CPU
{5CFE04A9-F65A-4EEF-B237-7608D19A87DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5CFE04A9-F65A-4EEF-B237-7608D19A87DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5CFE04A9-F65A-4EEF-B237-7608D19A87DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5CFE04A9-F65A-4EEF-B237-7608D19A87DE}.Release|Any CPU.Build.0 = Release|Any CPU
{913C7CBD-876C-45D8-B59E-D0849CD219E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{913C7CBD-876C-45D8-B59E-D0849CD219E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{913C7CBD-876C-45D8-B59E-D0849CD219E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{913C7CBD-876C-45D8-B59E-D0849CD219E4}.Release|Any CPU.Build.0 = Release|Any CPU
{32D8335E-E9E8-4AD8-BAE5-162F53AA4D72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{32D8335E-E9E8-4AD8-BAE5-162F53AA4D72}.Debug|Any CPU.Build.0 = Debug|Any CPU
{32D8335E-E9E8-4AD8-BAE5-162F53AA4D72}.Release|Any CPU.ActiveCfg = Release|Any CPU
{32D8335E-E9E8-4AD8-BAE5-162F53AA4D72}.Release|Any CPU.Build.0 = Release|Any CPU
{ED367118-BFB1-41CA-A010-E46C28796ED8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED367118-BFB1-41CA-A010-E46C28796ED8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED367118-BFB1-41CA-A010-E46C28796ED8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED367118-BFB1-41CA-A010-E46C28796ED8}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FDE61E04-DC84-437F-A176-40CD62CDE05F}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -113,11 +113,11 @@ namespace Scalar.CommandLine
copySubFolders: true);
}
// service ui
this.CopyAllFiles(
ScalarPlatform.Instance.GetCommonAppDataRootForScalar(),
archiveFolderPath,
ScalarConstants.Service.UIName,
// service ui
this.CopyAllFiles(
ScalarPlatform.Instance.GetCommonAppDataRootForScalar(),
archiveFolderPath,
ScalarConstants.Service.UIName,
copySubFolders: true);
if (ScalarPlatform.Instance.UnderConstruction.UsesCustomUpgrader)

Просмотреть файл

@ -1,69 +1,69 @@
Advanced Features
=================
Run Maintenance in the Foreground
---------------------------------
Scalar runs maintenance on your repositories in the background. You could
chose to run those maintenance steps yourself by running `scalar run <task> [<options>]`.
This command will run one maintenance step as specified by `<task>`. These
tasks are:
* `config`: Set recommended Git config settings. These are all intended
to improve performance in large repos. If the repo was cloned by Scalar,
then most of these settings will overwrite any existing settings. Otherwise,
Scalar will not override a local config value that disagrees with the
recommendation.
* `commit-graph`: Update the Git commit-graph to include all reachable
commits. After writing a new file, verify the file was computed successfully.
This drastically improves the performance of commands like `git log --graph`.
* `fetch`: Fetch the latest data from the remote servers. If using the GVFS
protocol, download the latest set of commit and tree packs from
the cache server or the origin remote. Otherwise, this step will fetch
the latest objects from each remote. This will not update your local
refs, so your `git fetch` commands will report all ref updates. Those
`git fetch` commands will be much faster as they will require much less
data transfer.
* `loose-objects`: Examine the loose objects contained in the shared object
cache. First, delete any loose objects that are currently located in
pack-files. Second, create a new pack-file containing the remaining loose
objects. The pack will contain up to 50,000 objects, leaving any extra
objects for the next run of the `loose-objects` step. This happens in the
background once a day.
* `pack-files`: Update the Git multi-pack-index and repack small pack-files
into larger pack-files. Scalar downloads many pack-files during the
`fetch` step, or during `git checkout` commands. The `pack-files`
step updates the Git multi-pack-index to improve lookup speed. Further, it
combines pack-files into larger files to reduce the total pack-file count.
This step is designed to work without blocking concurrent processes by only
deleting pack-files after they were marked as "unused" for at least a day.
This step allows using the `--batch-size=<size>` option. By default, the
batch-size is "2g" for two gigabytes. This batch size signifies the goal
size of a repacked pack-file.
* `all`: This task runs all of the above steps in the following order:
1. `config` ensures our recommended values are set for the remaining steps.
2. `fetch` downloads the latest data from the remotes.
3. `commit-graph` updates based on the newly fetched data.
4. `loose-objects` cleans up loose objects. When using the GVFS protocol,
the previous steps may have downloaded new loose objects.
5. `pack-files` cleans up the pack-files, including those downloaed in
previous steps.
Controlling Background Maintenance
----------------------------------
If you have a need to temporarily pause background maintenance from running,
then you can run `scalar pause [<number>]` to stop all maintenance for
`<number>` hours. If `<number>` is not provided, then maintenance will be
delayed for 12 hours.
For example, you may want to pause maintenance if you need all CPU resources
on your machine available for a high-performance activity or for performance
testing. You may also want to pause maintenance if you are on a metered
internet connection, as some of the maintenance downloads Git data from the
remote server.
Advanced Features
=================
Run Maintenance in the Foreground
---------------------------------
Scalar runs maintenance on your repositories in the background. You could
chose to run those maintenance steps yourself by running `scalar run <task> [<options>]`.
This command will run one maintenance step as specified by `<task>`. These
tasks are:
* `config`: Set recommended Git config settings. These are all intended
to improve performance in large repos. If the repo was cloned by Scalar,
then most of these settings will overwrite any existing settings. Otherwise,
Scalar will not override a local config value that disagrees with the
recommendation.
* `commit-graph`: Update the Git commit-graph to include all reachable
commits. After writing a new file, verify the file was computed successfully.
This drastically improves the performance of commands like `git log --graph`.
* `fetch`: Fetch the latest data from the remote servers. If using the GVFS
protocol, download the latest set of commit and tree packs from
the cache server or the origin remote. Otherwise, this step will fetch
the latest objects from each remote. This will not update your local
refs, so your `git fetch` commands will report all ref updates. Those
`git fetch` commands will be much faster as they will require much less
data transfer.
* `loose-objects`: Examine the loose objects contained in the shared object
cache. First, delete any loose objects that are currently located in
pack-files. Second, create a new pack-file containing the remaining loose
objects. The pack will contain up to 50,000 objects, leaving any extra
objects for the next run of the `loose-objects` step. This happens in the
background once a day.
* `pack-files`: Update the Git multi-pack-index and repack small pack-files
into larger pack-files. Scalar downloads many pack-files during the
`fetch` step, or during `git checkout` commands. The `pack-files`
step updates the Git multi-pack-index to improve lookup speed. Further, it
combines pack-files into larger files to reduce the total pack-file count.
This step is designed to work without blocking concurrent processes by only
deleting pack-files after they were marked as "unused" for at least a day.
This step allows using the `--batch-size=<size>` option. By default, the
batch-size is "2g" for two gigabytes. This batch size signifies the goal
size of a repacked pack-file.
* `all`: This task runs all of the above steps in the following order:
1. `config` ensures our recommended values are set for the remaining steps.
2. `fetch` downloads the latest data from the remotes.
3. `commit-graph` updates based on the newly fetched data.
4. `loose-objects` cleans up loose objects. When using the GVFS protocol,
the previous steps may have downloaded new loose objects.
5. `pack-files` cleans up the pack-files, including those downloaed in
previous steps.
Controlling Background Maintenance
----------------------------------
If you have a need to temporarily pause background maintenance from running,
then you can run `scalar pause [<number>]` to stop all maintenance for
`<number>` hours. If `<number>` is not provided, then maintenance will be
delayed for 12 hours.
For example, you may want to pause maintenance if you need all CPU resources
on your machine available for a high-performance activity or for performance
testing. You may also want to pause maintenance if you are on a metered
internet connection, as some of the maintenance downloads Git data from the
remote server.

Просмотреть файл

@ -1,87 +1,87 @@
Frequently Asked Questions
==========================
Using Scalar
------------
### I don't want a sparse clone, I want every file after I clone!
Run `scalar clone --full-clone <url>` to initialize your repo to include
every file. You can switch to a sparse-checkout later by running
`git sparse-checkout init --cone`.
### I already cloned without `--full-clone`. How do I get everything?
Run `git sparse-checkout disable`.
Scalar Design Decisions
-----------------------
There may be many design decisions within Scalar that are confusing at first
glance. Some of them may cause friction when you use Scalar with your existing
repos and existing habits.
> Scalar has the most benefit when users design repositories
> with efficient patterns.
For example: Scalar uses the sparse-checkout feature to limit the size of the
working directory within a large monorepo. It is designed to work efficiently
with monorepos that are highly componentized, allowing most developers to
need many fewer files in their daily work.
### Why does `scalar clone` create a `<repo>/src` folder?
Scalar uses a file system watcher to keep track of changes under this `src` folder.
Any activity in this folder is assumed to be important to Git operations. By
creating the `src` folder, we are making it easy for your build system to
create output folders outside the `src` directory. We commonly see systems
create folders for build outputs and package downloads. Scalar itself creates
these folders during its builds.
Your build system may create build artifacts such as `.obj` or `.lib` files
next to your source code. These are commonly "hidden" from Git using
`.gitignore` files. Having such artifacts into your source tree creates
additional work for Git because it needs to look at these files and match them
against the `.gitignore` patterns.
By following the pattern Scalar tries to establish and placing your build
intermediates and outputs parallel with the `src` folder and not inside it,
you can help optimize Git command performance for developers in the repository
by limiting the number of files Git needs to consider for many common
operations.
### Why is Scalar a C# tool instead of built directly into Git?
Currently, Scalar does a few things that Git does not do and a few
things that Git will never do.
Git does not have a concept of running background jobs, which is critical to
keeping our repositories running smoothly. Git does not have a concept of
cache servers, so we need to use the GVFS protocol during `scalar clone` to
set up the cache server URL. Scalar also creates the `.scalarCache` directory
so multiple enlistments share objects from the remote, allowing a second
`scalar clone` operation to be much faster than the first. All of these concepts
are on our backlog for contributing to Git. Once we do, we will transition
from the Scalar implementation to the Git implementation.
Scalar uses the GVFS protocol for some repositories. This protocol was created
by Azure Repos to support large repositories before the Git protocol supported
partial clone and the Git client supported missing objects. In a way, the GVFS
protocol proved that there was value in creating the partial clone feature.
This shows precedent for how our C# tools show value that leads to Git client
features. However, Git will never adopt the GVFS protocol, so we need to use
an tool other than the Git client to support teams that use it.
For now, Scalar requires a
[custom version of Git](https://github.com/microsoft/git), but we hope to relax
that restriction eventually.
We try to keep our fork of Git as close to [upstream](https://github.com/git-for-windows/git)
as we can, but some patches are necessary _for now_. Still, maintaining those
patches as we take updates from upstream has a significant cost. It is better
to create features in C# that use Git as a black box, then remove those C#
features as we contribute replacements to Git upstream.
Finally, as Git gains the features that we need in Scalar, Scalar will need to
support backwards compatibility with repositories cloned with older versions of
Scalar. Using the C# layer, we can update the Git version and upgrade old
repositories to whatever new features are added to Git.
Frequently Asked Questions
==========================
Using Scalar
------------
### I don't want a sparse clone, I want every file after I clone!
Run `scalar clone --full-clone <url>` to initialize your repo to include
every file. You can switch to a sparse-checkout later by running
`git sparse-checkout init --cone`.
### I already cloned without `--full-clone`. How do I get everything?
Run `git sparse-checkout disable`.
Scalar Design Decisions
-----------------------
There may be many design decisions within Scalar that are confusing at first
glance. Some of them may cause friction when you use Scalar with your existing
repos and existing habits.
> Scalar has the most benefit when users design repositories
> with efficient patterns.
For example: Scalar uses the sparse-checkout feature to limit the size of the
working directory within a large monorepo. It is designed to work efficiently
with monorepos that are highly componentized, allowing most developers to
need many fewer files in their daily work.
### Why does `scalar clone` create a `<repo>/src` folder?
Scalar uses a file system watcher to keep track of changes under this `src` folder.
Any activity in this folder is assumed to be important to Git operations. By
creating the `src` folder, we are making it easy for your build system to
create output folders outside the `src` directory. We commonly see systems
create folders for build outputs and package downloads. Scalar itself creates
these folders during its builds.
Your build system may create build artifacts such as `.obj` or `.lib` files
next to your source code. These are commonly "hidden" from Git using
`.gitignore` files. Having such artifacts into your source tree creates
additional work for Git because it needs to look at these files and match them
against the `.gitignore` patterns.
By following the pattern Scalar tries to establish and placing your build
intermediates and outputs parallel with the `src` folder and not inside it,
you can help optimize Git command performance for developers in the repository
by limiting the number of files Git needs to consider for many common
operations.
### Why is Scalar a C# tool instead of built directly into Git?
Currently, Scalar does a few things that Git does not do and a few
things that Git will never do.
Git does not have a concept of running background jobs, which is critical to
keeping our repositories running smoothly. Git does not have a concept of
cache servers, so we need to use the GVFS protocol during `scalar clone` to
set up the cache server URL. Scalar also creates the `.scalarCache` directory
so multiple enlistments share objects from the remote, allowing a second
`scalar clone` operation to be much faster than the first. All of these concepts
are on our backlog for contributing to Git. Once we do, we will transition
from the Scalar implementation to the Git implementation.
Scalar uses the GVFS protocol for some repositories. This protocol was created
by Azure Repos to support large repositories before the Git protocol supported
partial clone and the Git client supported missing objects. In a way, the GVFS
protocol proved that there was value in creating the partial clone feature.
This shows precedent for how our C# tools show value that leads to Git client
features. However, Git will never adopt the GVFS protocol, so we need to use
an tool other than the Git client to support teams that use it.
For now, Scalar requires a
[custom version of Git](https://github.com/microsoft/git), but we hope to relax
that restriction eventually.
We try to keep our fork of Git as close to [upstream](https://github.com/git-for-windows/git)
as we can, but some patches are necessary _for now_. Still, maintaining those
patches as we take updates from upstream has a significant cost. It is better
to create features in C# that use Git as a black box, then remove those C#
features as we contribute replacements to Git upstream.
Finally, as Git gains the features that we need in Scalar, Scalar will need to
support backwards compatibility with repositories cloned with older versions of
Scalar. Using the C# layer, we can update the Git version and upgrade old
repositories to whatever new features are added to Git.

Просмотреть файл

@ -1,112 +1,112 @@
Getting Started
===============
Registering existing Git repos
------------------------------
To add a repository to the list of registered repos, run `scalar register [<path>]`.
If `<path>` is not provided, then the "current repository" is discovered from
the working directory by scanning the parent paths for a path containing a `.git`
folder, possibly inside a `src` folder.
To see which repositories are currently tracked by the service, run
`scalar list`.
Run `scalar unregister [<path>]` to remove the repo from this list.
Creating a new Scalar clone using the GVFS Protocol
---------------------------------------------------
The `clone` verb creates a local enlistment of a remote repository using the
[GVFS protocol](https://github.com/microsoft/VFSForGit/blob/HEAD/Protocol.md).
```
scalar clone [options] <url> [<dir>]
```
Create a local copy of the repository at `<url>`. If specified, create the `<dir>`
directory and place the repository there. Otherwise, the last section of the `<url>`
will be used for `<dir>`.
At the end, the repo is located at `<dir>/src`. By default, the sparse-checkout
feature is enabled and the only files present are those in the root of your
Git repository. Use `git sparse-checkout set` to expand the set of directories
you want to see, or `git sparse-checkout disable` to expand to all files. You
can explore the subdirectories outside your sparse-checkout specification using
`git ls-tree HEAD`.
### Sparse Repo Mode
By default, Scalar reduces your working directory to the only the files at the
root of the repository. You need to add the folders you care about to build up
to your working set.
* `scalar clone <url>`
* Please choose the **Clone with HTTPS** option in the `Clone Repository` dialog in Azure Repos, not **Clone with SSH**.
* `cd <root>\src`
* At this point, your `src` directory only contains files that appear in your root
tree. No folders are populated.
* Set the directory list for your sparse-checkout using:
1. `git sparse-checkout set <dir1> <dir2> ...`
2. `git sparse-checkout set --stdin <dir-list.txt`
* Run git commands as you normally would.
* To fully populate your working directory, run `git sparse-checkout disable`.
If instead you want to start with all files on-disk, you can clone with the
`--full-clone` option. To enable sparse-checkout after the fact, run
`git sparse-checkout init --cone`. This will initialize your sparse-checkout
patterns to only match the files at root.
If you are unfamiliar with what directories are available in the repository,
then you can run `git ls-tree -d --name-only HEAD` to discover the directories
at root, or `git ls-tree -d --name-only HEAD <path>` to discover the directories
in `<path>`.
### Options
These options allow a user to customize their initial enlistment.
* `--full-clone`: If specified, do not initialize the sparse-checkout feature.
All files will be present in your `src` directory. This behaves very similar
to a Git partial clone in that blobs are downloaded on demand. However, it
will use the GVFS protocol to download all Git objects.
* `--cache-server-url=<url>`: If specified, set the intended cache server to
the specified `<url>`. All object queries will use the GVFS protocol to this
`<url>` instead of the origin remote. If the remote supplies a list of
cache servers via the `<url>/gvfs/config` endpoint, then the `clone` command
will select a nearby cache server from that list.
* `--branch=<ref>`: Specify the branch to checkout after clone.
* `--local-cache-path=<path>`: Use this option to override the path for the
local Scalar cache. If not specified, then Scalar will select a default
path to share objects with your other enlistments. On Windows, this path
is a subdirectory of `<Volume>:\.scalarCache\`. On Mac, this path is a
subdirectory of `~/.scalarCache/`. The default cache path is recommended so
multiple enlistments of the same remote repository share objects on the
same device.
### Advanced Options
The options below are not intended for use by a typical user. These are
usually used by build machines to create a temporary enlistment that
operates on a single commit.
* `--single-branch`: Use this option to only download metadata for the branch
that will be checked out. This is helpful for build machines that target
a remote with many branches. Any `git fetch` commands after the clone will
still ask for all branches.
* `--no-prefetch`: Use this option to not prefetch commits after clone. This
is not recommended for anyone planning to use their clone for history
traversal. Use of this option will make commands like `git log` or
`git pull` extremely slow and is therefore not recommended.
Removing a Scalar Clone
-----------------------
Since the `scalar clone` command sets up a file-system watcher (when available),
that watcher could prevent deleting the enlistment. Run `scalar delete <path>`
from outside of your enlistment to unregister the enlistment from the filesystem
watcher and delete the enlistment at `<path>`.
Getting Started
===============
Registering existing Git repos
------------------------------
To add a repository to the list of registered repos, run `scalar register [<path>]`.
If `<path>` is not provided, then the "current repository" is discovered from
the working directory by scanning the parent paths for a path containing a `.git`
folder, possibly inside a `src` folder.
To see which repositories are currently tracked by the service, run
`scalar list`.
Run `scalar unregister [<path>]` to remove the repo from this list.
Creating a new Scalar clone using the GVFS Protocol
---------------------------------------------------
The `clone` verb creates a local enlistment of a remote repository using the
[GVFS protocol](https://github.com/microsoft/VFSForGit/blob/HEAD/Protocol.md).
```
scalar clone [options] <url> [<dir>]
```
Create a local copy of the repository at `<url>`. If specified, create the `<dir>`
directory and place the repository there. Otherwise, the last section of the `<url>`
will be used for `<dir>`.
At the end, the repo is located at `<dir>/src`. By default, the sparse-checkout
feature is enabled and the only files present are those in the root of your
Git repository. Use `git sparse-checkout set` to expand the set of directories
you want to see, or `git sparse-checkout disable` to expand to all files. You
can explore the subdirectories outside your sparse-checkout specification using
`git ls-tree HEAD`.
### Sparse Repo Mode
By default, Scalar reduces your working directory to the only the files at the
root of the repository. You need to add the folders you care about to build up
to your working set.
* `scalar clone <url>`
* Please choose the **Clone with HTTPS** option in the `Clone Repository` dialog in Azure Repos, not **Clone with SSH**.
* `cd <root>\src`
* At this point, your `src` directory only contains files that appear in your root
tree. No folders are populated.
* Set the directory list for your sparse-checkout using:
1. `git sparse-checkout set <dir1> <dir2> ...`
2. `git sparse-checkout set --stdin <dir-list.txt`
* Run git commands as you normally would.
* To fully populate your working directory, run `git sparse-checkout disable`.
If instead you want to start with all files on-disk, you can clone with the
`--full-clone` option. To enable sparse-checkout after the fact, run
`git sparse-checkout init --cone`. This will initialize your sparse-checkout
patterns to only match the files at root.
If you are unfamiliar with what directories are available in the repository,
then you can run `git ls-tree -d --name-only HEAD` to discover the directories
at root, or `git ls-tree -d --name-only HEAD <path>` to discover the directories
in `<path>`.
### Options
These options allow a user to customize their initial enlistment.
* `--full-clone`: If specified, do not initialize the sparse-checkout feature.
All files will be present in your `src` directory. This behaves very similar
to a Git partial clone in that blobs are downloaded on demand. However, it
will use the GVFS protocol to download all Git objects.
* `--cache-server-url=<url>`: If specified, set the intended cache server to
the specified `<url>`. All object queries will use the GVFS protocol to this
`<url>` instead of the origin remote. If the remote supplies a list of
cache servers via the `<url>/gvfs/config` endpoint, then the `clone` command
will select a nearby cache server from that list.
* `--branch=<ref>`: Specify the branch to checkout after clone.
* `--local-cache-path=<path>`: Use this option to override the path for the
local Scalar cache. If not specified, then Scalar will select a default
path to share objects with your other enlistments. On Windows, this path
is a subdirectory of `<Volume>:\.scalarCache\`. On Mac, this path is a
subdirectory of `~/.scalarCache/`. The default cache path is recommended so
multiple enlistments of the same remote repository share objects on the
same device.
### Advanced Options
The options below are not intended for use by a typical user. These are
usually used by build machines to create a temporary enlistment that
operates on a single commit.
* `--single-branch`: Use this option to only download metadata for the branch
that will be checked out. This is helpful for build machines that target
a remote with many branches. Any `git fetch` commands after the clone will
still ask for all branches.
* `--no-prefetch`: Use this option to not prefetch commits after clone. This
is not recommended for anyone planning to use their clone for history
traversal. Use of this option will make commands like `git log` or
`git pull` extremely slow and is therefore not recommended.
Removing a Scalar Clone
-----------------------
Since the `scalar clone` command sets up a file-system watcher (when available),
that watcher could prevent deleting the enlistment. Run `scalar delete <path>`
from outside of your enlistment to unregister the enlistment from the filesystem
watcher and delete the enlistment at `<path>`.

Просмотреть файл

@ -1,74 +1,74 @@
Scalar: Enabling Git at Scale
=============================
Scalar is a tool that helps Git scale to some of the largest Git repositories.
It achieves this by enabling some advanced Git features, such as:
* *Sparse-checkout:* limits the size of your working directory.
* *File system monitor:* tracks the recently modified files and eliminates
the need for Git to scan the entire worktree.
* *Commit-graph:* accelerates commit walks and reachability calculations,
speeding up commands like `git log`.
* *Multi-pack-index:* enables fast object lookups across many pack-files.
* *Incremental repack:* Repacks the packed Git data into fewer pack-file
without disrupting concurrent commands by using the multi-pack-index.
By running `scalar register` in any Git repo, Scalar will automatically enable
these features for that repo and start running suggested maintenance in the
background.
Repos cloned with the `scalar clone` command use the
[GVFS protocol](https://github.com/microsoft/VFSForGit/blob/HEAD/Protocol.md)
to significantly reduce the amount of data required to get started
using a repository. By delaying all blob downloads until they are required,
Scalar allows you to work with very large repositories quickly. This protocol
allows a network of _cache servers_ to serve objects with lower latency and
higher throughput. The cache servers also reduce load on the central server.
Installing on macOS
------------------
To install Scalar on macOS,
[download the `Installers_macOS_Release.zip` from the releases page](https://github.com/microsoft/scalar/releases).
Extract the `Installers_macOS_Release` folder, `cd` into it, and run `./InstallScalar.sh` in a Terminal window.
The script may prompt for your password as it installs the following components:
* [Git](https://github.com/microsoft/git) (with custom patches)
* [Git Credential Manager Core](https://github.com/microsoft/Git-Credential-Manager-Core)
* Scalar
* [Watchman](https://github.com/facebook/watchman), unless you use the `--no-watchman` argument.
Installing on Windows
--------------------
To install Scalar on Windows,
[download the `Installers_Windows_Release.zip` from the releases page](https://github.com/microsoft/scalar/releases).
Extract the `Installers_Windows_Release` folder, open it in a command prompt, and
run `InstallScalar.bat`. This will install the following components:
* [Git for Windows](https://github.com/microsoft/git) (with custom patches)
* Scalar
* [Watchman](https://github.com/facebook/watchman), if you use the `--watchman` argument.
Documentation
-------------
* [Getting Started](getting-started.md): Get started with Scalar.
Includes `scalar register`, `scalar unregister`, `scalar clone`, and
`scalar delete`.
* [Advanced Features](advanced.md):
For expert users who want full control of Scalar's activity. Includes
`scalar run <task>`, `scalar pause`, `scalar resume`.
* [Troubleshooting](troubleshooting.md):
Collect diagnostic information or update custom settings. Includes
`scalar diagnose`, `scalar config`, `scalar upgrade`, and `scalar cache-server`.
* [The Philosophy of Scalar](philosophy.md): Why does Scalar work the way
it does, and how do we make decisions about its future?
* [Frequently Asked Questions](faq.md)
Scalar: Enabling Git at Scale
=============================
Scalar is a tool that helps Git scale to some of the largest Git repositories.
It achieves this by enabling some advanced Git features, such as:
* *Sparse-checkout:* limits the size of your working directory.
* *File system monitor:* tracks the recently modified files and eliminates
the need for Git to scan the entire worktree.
* *Commit-graph:* accelerates commit walks and reachability calculations,
speeding up commands like `git log`.
* *Multi-pack-index:* enables fast object lookups across many pack-files.
* *Incremental repack:* Repacks the packed Git data into fewer pack-file
without disrupting concurrent commands by using the multi-pack-index.
By running `scalar register` in any Git repo, Scalar will automatically enable
these features for that repo and start running suggested maintenance in the
background.
Repos cloned with the `scalar clone` command use the
[GVFS protocol](https://github.com/microsoft/VFSForGit/blob/HEAD/Protocol.md)
to significantly reduce the amount of data required to get started
using a repository. By delaying all blob downloads until they are required,
Scalar allows you to work with very large repositories quickly. This protocol
allows a network of _cache servers_ to serve objects with lower latency and
higher throughput. The cache servers also reduce load on the central server.
Installing on macOS
------------------
To install Scalar on macOS,
[download the `Installers_macOS_Release.zip` from the releases page](https://github.com/microsoft/scalar/releases).
Extract the `Installers_macOS_Release` folder, `cd` into it, and run `./InstallScalar.sh` in a Terminal window.
The script may prompt for your password as it installs the following components:
* [Git](https://github.com/microsoft/git) (with custom patches)
* [Git Credential Manager Core](https://github.com/microsoft/Git-Credential-Manager-Core)
* Scalar
* [Watchman](https://github.com/facebook/watchman), unless you use the `--no-watchman` argument.
Installing on Windows
--------------------
To install Scalar on Windows,
[download the `Installers_Windows_Release.zip` from the releases page](https://github.com/microsoft/scalar/releases).
Extract the `Installers_Windows_Release` folder, open it in a command prompt, and
run `InstallScalar.bat`. This will install the following components:
* [Git for Windows](https://github.com/microsoft/git) (with custom patches)
* Scalar
* [Watchman](https://github.com/facebook/watchman), if you use the `--watchman` argument.
Documentation
-------------
* [Getting Started](getting-started.md): Get started with Scalar.
Includes `scalar register`, `scalar unregister`, `scalar clone`, and
`scalar delete`.
* [Advanced Features](advanced.md):
For expert users who want full control of Scalar's activity. Includes
`scalar run <task>`, `scalar pause`, `scalar resume`.
* [Troubleshooting](troubleshooting.md):
Collect diagnostic information or update custom settings. Includes
`scalar diagnose`, `scalar config`, `scalar upgrade`, and `scalar cache-server`.
* [The Philosophy of Scalar](philosophy.md): Why does Scalar work the way
it does, and how do we make decisions about its future?
* [Frequently Asked Questions](faq.md)

Просмотреть файл

@ -1,65 +1,65 @@
The Philosophy of Scalar
========================
The team building Scalar has **opinions** about Git performance. Scalar
takes out the guesswork by automatically configuring your Git repositories
to take advantage of the latest and greatest features. It is difficult to
say that these are the absolute best settings for every repository, but
these settings do work for some of the largest repositories in the world.
Scalar intends to do very little more than the standard Git client. We
actively implement new features into Git instead of Scalar, then update
Scalar only to configure those new settings. In particular, we are porting
features like background maintenance to Git to make Scalar simpler and
make Git more powerful.
Scalar ships with [a custom version of Git][microsoft-git],
but performs most of its benefits without that version. The only feature
that is not intended to ever reach the standard Git client is Scalar's use
of [the GVFS Protocol][gvfs-protocol].
The GVFS Protocol is a way to reduce object transfer between client and
server, named for its use in [VFS for Git](https://github.com/microsoft/vfsforgit).
If you don't use the GVFS Protocol, then most of the value of Scalar can
be found in the core Git client. However, most of the advanced features
that really optimize Git's performance are off by default for compatibility
reasons. To really take advantage of Git's latest and greatest features,
you either need to study the [`git config` documentation](https://git-scm.com/docs/git-config)
and regularly read [the Git release notes](https://github.com/git/git/tree/master/Documentation/RelNotes).
Even if you do all that work and customize your Git settings on your machines,
you likely will want to share those settings with other team members.
Or, you can just use Scalar!
Using `scalar register` on an existing Git repository will give you these
benefits:
* Additional compression of your `.git/index` file.
* Hourly background `git fetch` operations, keeping you in-sync with your
remotes.
* Advanced data structures, such as the `commit-graph` and `multi-pack-index`
are updated automatically in the background.
* If Watchman is installed, then the FileSystem Monitor hook is configured
to use Watchman's change-tracking, providing faster commands such as
`git status` or `git add`.
Additionally, if you use `scalar clone` to create a new repository, then
you will automatically get these benefits:
* Use Git's partial clone feature to only download the files you need for
your current checkout.
* Use Git's [sparse-checkout feature][sparse-checkout] to minimize the
number of files required in your working directory.
[Read more about sparse-checkout here.][sparse-checkout-blog]
* Create the Git repository inside `<repo-name>/src` to make it easy to
place build artifacts outside of the Git repository, such as in
`<repo-name>/bin` or `<repo-name>/packages`.
We also admit that these **opinions** can always be improved! If you have
an idea of how to improve our setup, consider [creating an issue](https://github.com/microsoft/scalar/issues/new) or contributing a pull request! Some [existing](https://github.com/microsoft/scalar/issues/382)
[issues](https://github.com/microsoft/scalar/issues/388) have already
improved our configuration settings and roadmap!
[gvfs-protocol]: https://github.com/microsoft/VFSForGit/blob/HEAD/Protocol.md
[microsoft-git]: https://github.com/microsoft/git
[sparse-checkout]: https://git-scm.com/docs/git-sparse-checkout
[sparse-checkout-blog]: https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/
The Philosophy of Scalar
========================
The team building Scalar has **opinions** about Git performance. Scalar
takes out the guesswork by automatically configuring your Git repositories
to take advantage of the latest and greatest features. It is difficult to
say that these are the absolute best settings for every repository, but
these settings do work for some of the largest repositories in the world.
Scalar intends to do very little more than the standard Git client. We
actively implement new features into Git instead of Scalar, then update
Scalar only to configure those new settings. In particular, we are porting
features like background maintenance to Git to make Scalar simpler and
make Git more powerful.
Scalar ships with [a custom version of Git][microsoft-git],
but performs most of its benefits without that version. The only feature
that is not intended to ever reach the standard Git client is Scalar's use
of [the GVFS Protocol][gvfs-protocol].
The GVFS Protocol is a way to reduce object transfer between client and
server, named for its use in [VFS for Git](https://github.com/microsoft/vfsforgit).
If you don't use the GVFS Protocol, then most of the value of Scalar can
be found in the core Git client. However, most of the advanced features
that really optimize Git's performance are off by default for compatibility
reasons. To really take advantage of Git's latest and greatest features,
you either need to study the [`git config` documentation](https://git-scm.com/docs/git-config)
and regularly read [the Git release notes](https://github.com/git/git/tree/master/Documentation/RelNotes).
Even if you do all that work and customize your Git settings on your machines,
you likely will want to share those settings with other team members.
Or, you can just use Scalar!
Using `scalar register` on an existing Git repository will give you these
benefits:
* Additional compression of your `.git/index` file.
* Hourly background `git fetch` operations, keeping you in-sync with your
remotes.
* Advanced data structures, such as the `commit-graph` and `multi-pack-index`
are updated automatically in the background.
* If Watchman is installed, then the FileSystem Monitor hook is configured
to use Watchman's change-tracking, providing faster commands such as
`git status` or `git add`.
Additionally, if you use `scalar clone` to create a new repository, then
you will automatically get these benefits:
* Use Git's partial clone feature to only download the files you need for
your current checkout.
* Use Git's [sparse-checkout feature][sparse-checkout] to minimize the
number of files required in your working directory.
[Read more about sparse-checkout here.][sparse-checkout-blog]
* Create the Git repository inside `<repo-name>/src` to make it easy to
place build artifacts outside of the Git repository, such as in
`<repo-name>/bin` or `<repo-name>/packages`.
We also admit that these **opinions** can always be improved! If you have
an idea of how to improve our setup, consider [creating an issue](https://github.com/microsoft/scalar/issues/new) or contributing a pull request! Some [existing](https://github.com/microsoft/scalar/issues/382)
[issues](https://github.com/microsoft/scalar/issues/388) have already
improved our configuration settings and roadmap!
[gvfs-protocol]: https://github.com/microsoft/VFSForGit/blob/HEAD/Protocol.md
[microsoft-git]: https://github.com/microsoft/git
[sparse-checkout]: https://git-scm.com/docs/git-sparse-checkout
[sparse-checkout-blog]: https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout/

Просмотреть файл

@ -1,59 +1,59 @@
Troubleshooting
===============
Upgrade
-------
The Scalar service checks for new versions of Scalar daily and will prompt you
for upgrade using a notification. To check yourself, run `scalar upgrade` to
see if an upgrade is available. Run `scalar upgrade --confirm` to actually
perform the upgrade, if you wish.
Diagnosing Issues
-----------------
The `scalar diagnose` command collects logs and config details for the current
repository. The resulting zip file helps root-cause issues.
When run inside your repository, creates a zip file containing several important
files for that repository. This includes:
* All log files from `scalar` commands run in the enlistment, including
maintenance steps.
* Log files from the Scalar service.
* Configuration files from your `.git` folder, such as the `config` file,
`index`, `hooks`, and `refs`.
* A summary of your Git object database, including the number of loose objects
and the names and sizes of pack-files.
As the `diagnose` command completes, it provides the path of the resulting
zip file. This zip can be sent to the support team for investigation.
Modifying Configuration Values
------------------------------
The Scalar-specific configuration is only available for repos using the
GVFS protocol.
### Cache Server URL
When using an enlistment cloned with `scalar clone` and the GVFS protocol,
you will have a value called the cache server URL. Cache servers are a feature
of the GVFS protocol to provide low-latency access to the on-demand object
requests. This modifies the `gvfs.cache-server` setting in your local Git config
file.
Run `scalar cache-server --get` to see the current cache server.
Run `scalar cache-server --list` to see the available cache server URLs.
Run `scalar cache-server --set=<url>` to set your cache server to `<url>`.
### Scalar Config
The `scalar config` command is used for customizing the feed used for
Scalar upgrades. This is so large teams can bundle a custom installer
or other tools along with Scalar upgrades.
Troubleshooting
===============
Upgrade
-------
The Scalar service checks for new versions of Scalar daily and will prompt you
for upgrade using a notification. To check yourself, run `scalar upgrade` to
see if an upgrade is available. Run `scalar upgrade --confirm` to actually
perform the upgrade, if you wish.
Diagnosing Issues
-----------------
The `scalar diagnose` command collects logs and config details for the current
repository. The resulting zip file helps root-cause issues.
When run inside your repository, creates a zip file containing several important
files for that repository. This includes:
* All log files from `scalar` commands run in the enlistment, including
maintenance steps.
* Log files from the Scalar service.
* Configuration files from your `.git` folder, such as the `config` file,
`index`, `hooks`, and `refs`.
* A summary of your Git object database, including the number of loose objects
and the names and sizes of pack-files.
As the `diagnose` command completes, it provides the path of the resulting
zip file. This zip can be sent to the support team for investigation.
Modifying Configuration Values
------------------------------
The Scalar-specific configuration is only available for repos using the
GVFS protocol.
### Cache Server URL
When using an enlistment cloned with `scalar clone` and the GVFS protocol,
you will have a value called the cache server URL. Cache servers are a feature
of the GVFS protocol to provide low-latency access to the on-demand object
requests. This modifies the `gvfs.cache-server` setting in your local Git config
file.
Run `scalar cache-server --get` to see the current cache server.
Run `scalar cache-server --list` to see the available cache server URLs.
Run `scalar cache-server --set=<url>` to set your cache server to `<url>`.
### Scalar Config
The `scalar config` command is used for customizing the feed used for
Scalar upgrades. This is so large teams can bundle a custom installer
or other tools along with Scalar upgrades.