Skip to content

Commit

Permalink
[Hosts] Improved duplicate hosts finding (#24294)
Browse files Browse the repository at this point in the history
* improved duplicate hosts finding

* improved filters with AdvancedCollectionView

* cancel FindDuplicates when file is reloaded
  • Loading branch information
davidegiacometti committed Feb 27, 2023
1 parent 0d9b797 commit 3e651b8
Show file tree
Hide file tree
Showing 14 changed files with 290 additions and 83 deletions.
6 changes: 3 additions & 3 deletions src/modules/Hosts/Hosts.Tests/EntryTest.cs
Expand Up @@ -28,7 +28,7 @@ public class EntryTest
[DataRow("# # \t10.1.1.1 host#comment", "10.1.1.1", "host", "comment", false)]
public void Valid_Entry_SingleHost(string line, string address, string host, string comment, bool active)
{
var entry = new Entry(line);
var entry = new Entry(0, line);

Assert.AreEqual(entry.Address, address);
Assert.AreEqual(entry.Hosts, host);
Expand All @@ -52,7 +52,7 @@ public void Valid_Entry_SingleHost(string line, string address, string host, str
[DataRow("#10.1.1.1 host host.local#comment", "10.1.1.1", "host host.local", "comment", false)]
public void Valid_Entry_MultipleHosts(string line, string address, string host, string comment, bool active)
{
var entry = new Entry(line);
var entry = new Entry(0, line);

Assert.AreEqual(entry.Address, address);
Assert.AreEqual(entry.Hosts, host);
Expand All @@ -76,7 +76,7 @@ public void Valid_Entry_MultipleHosts(string line, string address, string host,
[DataRow("host 10.1.1.1")]
public void Not_Valid_Entry(string line)
{
var entry = new Entry(line);
var entry = new Entry(0, line);
Assert.IsFalse(entry.Valid);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/modules/Hosts/Hosts.Tests/HostsServiceTest.cs
Expand Up @@ -70,7 +70,7 @@ public async Task Host_Added()
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));

var (_, entries) = await service.ReadAsync();
entries.Add(new Entry("10.1.1.30", "host30 host30.local", "new entry", false));
entries.Add(new Entry(0, "10.1.1.30", "host30 host30.local", "new entry", false));
await service.WriteAsync(string.Empty, entries);

var result = fileSystem.GetFile(service.HostsFilePath);
Expand Down
43 changes: 43 additions & 0 deletions src/modules/Hosts/Hosts/Helpers/ExpressionExtensions.cs
@@ -0,0 +1,43 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Linq.Expressions;

namespace Hosts.Helpers
{
// https://stackoverflow.com/a/22569086
public static class ExpressionExtensions
{
public static Expression<Func<T, bool>> And<T>(
this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var secondBody = expr2.Body.Replace(expr2.Parameters[0], expr1.Parameters[0]);
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, secondBody), expr1.Parameters);
}

public static Expression Replace(this Expression expression, Expression searchEx, Expression replaceEx)
{
return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}

internal class ReplaceVisitor : ExpressionVisitor
{
private readonly Expression _from;
private readonly Expression _to;

public ReplaceVisitor(Expression from, Expression to)
{
_from = from;
_to = to;
}

public override Expression Visit(Expression node)
{
return node == _from ? _to : base.Visit(node);
}
}
}
}
2 changes: 1 addition & 1 deletion src/modules/Hosts/Hosts/Helpers/HostsService.cs
Expand Up @@ -82,7 +82,7 @@ public async Task<(string Unparsed, List<Entry> Entries)> ReadAsync()
continue;
}

var entry = new Entry(line);
var entry = new Entry(i, line);

if (entry.Valid)
{
Expand Down
13 changes: 13 additions & 0 deletions src/modules/Hosts/Hosts/Models/AddressType.cs
@@ -0,0 +1,13 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace Hosts.Models
{
public enum AddressType
{
Invalid = 0,
IPv4 = 1,
IPv6 = 2,
}
}
29 changes: 26 additions & 3 deletions src/modules/Hosts/Hosts/Models/Entry.cs
Expand Up @@ -22,6 +22,7 @@ public string Address
set
{
SetProperty(ref _address, value);
SetAddressType();
OnPropertyChanged(nameof(Valid));
}
}
Expand Down Expand Up @@ -54,22 +55,28 @@ public string Hosts
[ObservableProperty]
private bool _duplicate;

public bool Valid => ValidationHelper.ValidHosts(_hosts) && (ValidationHelper.ValidIPv4(_address) || ValidationHelper.ValidIPv6(_address));
public bool Valid => ValidationHelper.ValidHosts(_hosts) && Type != AddressType.Invalid;

public AddressType Type { get; private set; }

public string[] SplittedHosts { get; private set; }

public int Id { get; set; }

public Entry()
{
}

public Entry(string line)
public Entry(int id, string line)
{
Id = id;
_line = line.Trim();
Parse();
}

public Entry(string address, string hosts, string comment, bool active)
public Entry(int id, string address, string hosts, string comment, bool active)
{
Id = id;
Address = address.Trim();
Hosts = hosts.Trim();
Comment = comment.Trim();
Expand Down Expand Up @@ -151,5 +158,21 @@ public string GetLine()
{
return _line;
}

private void SetAddressType()
{
if (ValidationHelper.ValidIPv4(_address))
{
Type = AddressType.IPv4;
}
else if (ValidationHelper.ValidIPv6(_address))
{
Type = AddressType.IPv6;
}
else
{
Type = AddressType.Invalid;
}
}
}
}
5 changes: 5 additions & 0 deletions src/modules/Hosts/Hosts/Settings/IUserSettings.cs
Expand Up @@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using Settings.UI.Library.Enumerations;

namespace Hosts.Settings
Expand All @@ -10,6 +11,10 @@ public interface IUserSettings
{
public bool ShowStartupWarning { get; }

public bool LoopbackDuplicates { get; }

public AdditionalLinesPosition AdditionalLinesPosition { get; }

event EventHandler LoopbackDuplicatesChanged;
}
}
19 changes: 19 additions & 0 deletions src/modules/Hosts/Hosts/Settings/UserSettings.cs
Expand Up @@ -22,19 +22,37 @@ public class UserSettings : IUserSettings

public bool ShowStartupWarning { get; private set; }

private bool _loopbackDuplicates;

public bool LoopbackDuplicates
{
get => _loopbackDuplicates;
set
{
if (_loopbackDuplicates != value)
{
_loopbackDuplicates = value;
LoopbackDuplicatesChanged?.Invoke(this, EventArgs.Empty);
}
}
}

public AdditionalLinesPosition AdditionalLinesPosition { get; private set; }

public UserSettings()
{
_settingsUtils = new SettingsUtils();
ShowStartupWarning = true;
LoopbackDuplicates = false;
AdditionalLinesPosition = AdditionalLinesPosition.Top;

LoadSettingsFromJson();

_watcher = Helper.GetFileWatcher(HostsModuleName, "settings.json", () => LoadSettingsFromJson());
}

public event EventHandler LoopbackDuplicatesChanged;

private void LoadSettingsFromJson()
{
lock (_loadingSettingsLock)
Expand All @@ -60,6 +78,7 @@ private void LoadSettingsFromJson()
{
ShowStartupWarning = settings.Properties.ShowStartupWarning;
AdditionalLinesPosition = settings.Properties.AdditionalLinesPosition;
LoopbackDuplicates = settings.Properties.LoopbackDuplicates;
}

retry = false;
Expand Down

0 comments on commit 3e651b8

Please sign in to comment.