Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into homepage-implemen…
Browse files Browse the repository at this point in the history
…tation
  • Loading branch information
dnenov committed Feb 7, 2024
2 parents ecf3020 + d01e057 commit e7d4a6d
Show file tree
Hide file tree
Showing 12 changed files with 293 additions and 92 deletions.
55 changes: 48 additions & 7 deletions src/DynamoCore/Utilities/LuceneSearchUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,18 @@ internal void SetDocumentFieldValue(Document doc, string field, string value, bo
}
}

/// <summary>
/// Check if the term passed as parameter is found inside the FullCategoryName
/// </summary>
/// <param name="term">Splitted search term e.g. if the search term is "set parameter" the parameter will be "set" or "parameter"</param>
/// <param name="FullCategoryName">The complete category used for a specific node, like Core.File.FileSystem</param>
/// <returns></returns>
private bool IsMatchingCategory(string term, string FullCategoryName)
{
var categoryTerms = FullCategoryName.Split(".").Select(x => x.ToLower());
return categoryTerms.Contains(term);
}

/// <summary>
/// Creates a search query with adjusted priority, fuzzy logic and wildcards.
/// Complete Search term appearing in Name of the package will be given highest priority.
Expand Down Expand Up @@ -306,6 +318,8 @@ internal string CreateSearchQuery(string[] fields, string SearchTerm)

foreach (string f in fields)
{
Occur occurQuery = Occur.SHOULD;

//Needs to be again due that now a query can contain different values per field (e.g. CategorySplitted:list, Name:tr)
searchTerm = QueryParser.Escape(SearchTerm);
if (searchType == SearchType.ByCategory)
Expand Down Expand Up @@ -335,6 +349,36 @@ internal string CreateSearchQuery(string[] fields, string SearchTerm)
if (string.IsNullOrEmpty(searchTerm))
continue;

bool firstTermIsCategory = false;

//This will only valid when the search term has empty spaces
if (hasEmptySpaces)
{
//Check if the first term of the search criteria match any category
var possibleCategory = searchTerm.Split(' ')[0];
if (string.IsNullOrEmpty(possibleCategory)) continue;

var specificCategoryEntries = dynamoModel.SearchModel.Entries.Where(entry => IsMatchingCategory(possibleCategory, entry.FullCategoryName) == true);
firstTermIsCategory = specificCategoryEntries.Any();

//Get the node matching the Category provided in the search term
var matchingCategory = specificCategoryEntries.FirstOrDefault();
if (matchingCategory == null && firstTermIsCategory == true) continue;

if (f == nameof(LuceneConfig.NodeFieldsEnum.FullCategoryName) && firstTermIsCategory == true)
{
//Means that the first term is a category when we will be using the FullCategoryName for making a specific search based in the category
trimmedSearchTerm = matchingCategory?.FullCategoryName;
occurQuery = Occur.MUST;
}
else if (f == nameof(LuceneConfig.NodeFieldsEnum.Name) && firstTermIsCategory == true)
{
//If the field being iterated is Name and we are sure that the first term is a Category when we remove the term from the string so we can search for the specific node Name
trimmedSearchTerm = trimmedSearchTerm?.Replace(possibleCategory, string.Empty);
if (string.IsNullOrEmpty(trimmedSearchTerm)) continue;
}
}

FuzzyQuery fuzzyQuery;
if (searchTerm.Length > LuceneConfig.FuzzySearchMinimalTermLength)
{
Expand All @@ -347,14 +391,11 @@ internal string CreateSearchQuery(string[] fields, string SearchTerm)

if (searchType == SearchType.ByCategory && f == nameof(LuceneConfig.NodeFieldsEnum.CategorySplitted))
{
booleanQuery.Add(fieldQuery, Occur.MUST);
booleanQuery.Add(wildcardQuery, Occur.MUST);
}
else
{
booleanQuery.Add(fieldQuery, Occur.SHOULD);
booleanQuery.Add(wildcardQuery, Occur.SHOULD);
occurQuery = Occur.MUST;
}

booleanQuery.Add(fieldQuery, occurQuery);
booleanQuery.Add(wildcardQuery, occurQuery);

if (searchTerm.Contains(' '))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,14 @@ internal void AddChildren(PackageItemRootViewModel item)
if (this.ChildItems.Contains(item)) return;
this.ChildItems.Add(item);
}

internal void AddChild(PackageItemRootViewModel elem)
/// <summary>
/// The methods is used for adding a child item to all the encountered parent folders in a nested path
/// and make sure all the intermediate file paths are created as separate PackageItemRootViewModel.
/// For example if we have a path like "\dir1\dir2\dir3" and we want to add a child item to "dir1", the method will
/// add "dir 3" to "dir2" and then "dir2" to "dir1".
/// </summary>
/// <param name="elem">Child item to be added.</param>
internal void AddChildRecursively(PackageItemRootViewModel elem)
{
if (elem.DependencyType.Equals(DependencyType.CustomNode)) return;

Expand All @@ -149,7 +155,7 @@ internal void AddChild(PackageItemRootViewModel elem)

while (di.Parent != null)
{
// if we already have a subfodler item with that name,
// if we already have a subfolder item with that name,
// add this element's children to its children instead of creating a new subfolder branch
if(existingSubFolders.Keys.Contains(elem.DirectoryName))
{
Expand Down
100 changes: 80 additions & 20 deletions src/DynamoCoreWpf/ViewModels/PackageManager/PublishPackageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -893,6 +893,10 @@ public bool RetainFolderStructureOverride
}
}
}
/// <summary>
/// The root directory of the package
/// </summary>
private string CurrentPackageDirectory { get; set; }
private static MetadataLoadContext sharedMetaDataLoadContext = null;
/// <summary>
/// A shared MetaDataLoadContext that is used for assembly inspection during package publishing.
Expand Down Expand Up @@ -996,7 +1000,7 @@ private void RefreshPackageContents()

var items = new Dictionary<string, PackageItemRootViewModel>();

if(!String.IsNullOrEmpty(RootFolder))
if (!String.IsNullOrEmpty(RootFolder))
{
var root = new PackageItemRootViewModel(RootFolder);
items[RootFolder] = root;
Expand All @@ -1022,7 +1026,7 @@ private void RefreshPackageContents()
}
}

var updatedItems = BindParentToChild(items);
var updatedItems = BindParentToChild(items);

updatedItems.AddRange(itemsToAdd.Where(pa => pa.DependencyType.Equals(DependencyType.CustomNode)));

Expand Down Expand Up @@ -1050,8 +1054,6 @@ private bool IsDuplicateFile(PackageItemRootViewModel item1, PackageItemRootView

private List<PackageItemRootViewModel> BindParentToChild(Dictionary<string, PackageItemRootViewModel> items)
{
var updatedItems = new List<PackageItemRootViewModel>();

foreach (var parent in items)
{
foreach(var child in items)
Expand All @@ -1060,25 +1062,53 @@ private List<PackageItemRootViewModel> BindParentToChild(Dictionary<string, Pack
if (IsSubPathOfDeep(parent.Value, child.Value))
{
if (child.Value.isChild) continue; // if this was picked up already, don't add it again
parent.Value.AddChild(child.Value);
parent.Value.AddChildRecursively(child.Value);
child.Value.isChild = true;
}
}
}

// Only add the folder items, they contain the files
updatedItems = items.Values.Where(x => !x.isChild).ToList();
var updatedItems = GetRootItems(items);
return updatedItems;
}

/// <summary>
/// Gets the list PackageItemRootViewModel items which will be at the root directory of the package with all the child items.
/// </summary>
/// <param name="items"></param>
/// <returns></returns>
private List<PackageItemRootViewModel> GetRootItems(Dictionary<string, PackageItemRootViewModel> items)
{
var rootItems = items.Values.Where(x => !x.isChild).ToList();
if (!rootItems.Any()) return rootItems;
var packageSourceDir = CurrentPackageDirectory ??= GetLongestCommonPrefix(items.Keys.ToArray());

var root = new PackageItemRootViewModel(packageSourceDir);
var updatedItems = new List<PackageItemRootViewModel>();
//check each root item and create any missing connections
foreach (var item in rootItems)
{
var itemDir = new DirectoryInfo(item.DirectoryName);
if (!itemDir.Parent.FullName.Equals(packageSourceDir))
{
root.AddChildRecursively(item);
}
else
{
root.ChildItems.Add(item);
}
}
return root.ChildItems.ToList();
}

/// <summary>
/// Test if path2 is subpath of path1
/// If it is, make sure all the intermediate file paths are created as separte PackageItemRootViewModel
/// </summary>
/// <param name="path1"></param>
/// <param name="path2"></param>
/// <returns></returns>
private bool IsSubPathOfDeep(PackageItemRootViewModel path1, PackageItemRootViewModel path2)
internal bool IsSubPathOfDeep(PackageItemRootViewModel path1, PackageItemRootViewModel path2)
{
var di1 = new DirectoryInfo(path1.DirectoryName);
var di2 = new DirectoryInfo(path2.DirectoryName);
Expand All @@ -1089,12 +1119,37 @@ private bool IsSubPathOfDeep(PackageItemRootViewModel path1, PackageItemRootView
{
return true;
}
else di2 = di2.Parent;
else
{
if (di2.Parent.FullName.Length < di1.FullName.Length) return false;
di2 = di2.Parent;
}
}

return false;
}

/// <summary>
/// Utility method to get the common file path, this may fail for files with the same partial name.
/// </summary>
/// <param name="s">A collection of filepaths</param>
/// <returns></returns>
internal string GetLongestCommonPrefix(string[] s)
{
int k = s[0].Length;
for (int i = 1; i < s.Length; i++)
{
k = Math.Min(k, s[i].Length);
for (int j = 0; j < k; j++)
if (s[i][j] != s[0][j])
{
k = j;
break;
}
}
return Path.GetDirectoryName(s[0].Substring(0, k));
}

/// <summary>
/// Return a list of HostComboboxEntry describing known hosts from PM.
/// Return an empty list if PM is down.
Expand Down Expand Up @@ -1403,6 +1458,7 @@ internal static PublishPackageViewModel FromLocalPackage(DynamoViewModel dynamoV
CopyrightHolder = pkg.CopyrightHolder,
CopyrightYear = pkg.CopyrightYear,
IsPublishFromLocalPackage = true,
CurrentPackageDirectory = pkg.RootDirectory,
//default retain folder structure to true when publishing a new version from local.
RetainFolderStructureOverride = retainFolderStructure
};
Expand Down Expand Up @@ -1636,7 +1692,7 @@ internal IEnumerable<string> GetAllFiles()
// union with additional files
files = files.Union(AdditionalFiles);
// if we retain the folder structure, we don't want to lose assemblies in sub-folders
// othrewise we need to delete duplicate assemblies which will end up in the same `dll` folder
// otherwise we need to delete duplicate assemblies which will end up in the same `dll` folder
files = RetainFolderStructureOverride && !IsPublishFromLocalPackage ?
files.Union(Assemblies.Select(x => x.LocalFilePath)) :
files.Union(Assemblies.Select(x => x.Assembly.Location));
Expand Down Expand Up @@ -2232,6 +2288,10 @@ private void PublishLocally()
var remapper = new CustomNodePathRemapper(DynamoViewModel.Model.CustomNodeManager,
DynamoModel.IsTestMode);
var builder = new PackageDirectoryBuilder(new MutatingFileSystem(), remapper);
if (string.IsNullOrEmpty(Package.RootDirectory))
{
Package.RootDirectory = CurrentPackageDirectory;
}
builder.BuildRetainDirectory(Package, publishPath, updatedFiles, MarkdownFiles);
UploadState = PackageUploadHandle.State.Uploaded;
}
Expand Down Expand Up @@ -2647,7 +2707,7 @@ internal PackageItemRootViewModel GetPreBuildRootItemViewModel(string publishPat
var docItemPreview = new PackageItemRootViewModel(docDir) { isChild = true };

var pkg = new PackageItemRootViewModel(new FileInfo(Path.Combine(rootDir, "pkg.json")));
rootItemPreview.AddChild(pkg);
rootItemPreview.AddChildRecursively(pkg);

foreach (var file in files)
{
Expand All @@ -2657,12 +2717,12 @@ internal PackageItemRootViewModel GetPreBuildRootItemViewModel(string publishPat
if (Path.GetDirectoryName(file).EndsWith(PackageDirectoryBuilder.DocumentationDirectoryName))
{
var doc = new PackageItemRootViewModel(new FileInfo(Path.Combine(docDir, fileName)));
docItemPreview.AddChild(doc);
docItemPreview.AddChildRecursively(doc);
}
else if (file.EndsWith(".dyf"))
{
var dyfPreview = new PackageItemRootViewModel(fileName, Path.Combine(dyfDir, fileName));
dyfItemPreview.AddChild(dyfPreview);
dyfItemPreview.AddChildRecursively(dyfPreview);
}
else if (file.EndsWith(".dll") || PackageDirectoryBuilder.IsXmlDocFile(file, files) || PackageDirectoryBuilder.IsDynamoCustomizationFile(file, files))
{
Expand All @@ -2677,27 +2737,27 @@ internal PackageItemRootViewModel GetPreBuildRootItemViewModel(string publishPat
else
{
var dll = new PackageItemRootViewModel(new FileInfo(Path.Combine(binDir, fileName)));
binItemPreview.AddChild(dll);
binItemPreview.AddChildRecursively(dll);
}
}
else
{
var extra = new PackageItemRootViewModel(new FileInfo(Path.Combine(extraDir, fileName)));
extraItemPreview.AddChild(extra);
extraItemPreview.AddChildRecursively(extra);
}
}

foreach(var docFile in MarkdownFiles)
{
var fileName = Path.GetFileName(docFile);
var doc = new PackageItemRootViewModel(new FileInfo(Path.Combine(docDir, fileName)));
docItemPreview.AddChild(doc);
docItemPreview.AddChildRecursively(doc);
}

rootItemPreview.AddChild(dyfItemPreview);
rootItemPreview.AddChild(binItemPreview);
rootItemPreview.AddChild(extraItemPreview);
rootItemPreview.AddChild(docItemPreview);
rootItemPreview.AddChildRecursively(dyfItemPreview);
rootItemPreview.AddChildRecursively(binItemPreview);
rootItemPreview.AddChildRecursively(extraItemPreview);
rootItemPreview.AddChildRecursively(docItemPreview);

return rootItemPreview;
}
Expand Down
Loading

0 comments on commit e7d4a6d

Please sign in to comment.