Port TimeSpan multiplication and division operators (#2870)

Closes dotnet/corefx#7175

--- src/System.Private.CoreLib/src/System/TimeSpan.cs
+++ src/System.Private.CoreLib/src/System/TimeSpan.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.

@@ -396,6 +396,48 @@
             return t1.Add(t2);
         }

+        public static TimeSpan operator *(TimeSpan timeSpan, double factor)
+        {
+            if (double.IsNaN(factor))
+            {
+                throw new ArgumentException(SR.Arg_CannotBeNaN, nameof(factor));
+            }
+
+            // Rounding to the nearest tick is as close to the result we would have with unlimited
+            // precision as possible, and so likely to have the least potential to surprise.
+            double ticks = Math.Round(timeSpan.Ticks * factor);
+            if (ticks > long.MaxValue | ticks < long.MinValue)
+            {
+                throw new OverflowException(SR.Overflow_TimeSpanTooLong);
+            }
+
+            return FromTicks((long)ticks);
+        }
+
+        public static TimeSpan operator *(double factor, TimeSpan timeSpan) => timeSpan * factor;
+
+        public static TimeSpan operator /(TimeSpan timeSpan, double divisor)
+        {
+            if (double.IsNaN(divisor))
+            {
+                throw new ArgumentException(SR.Arg_CannotBeNaN, nameof(divisor));
+            }
+
+            double ticks = Math.Round(timeSpan.Ticks / divisor);
+            if (ticks > long.MaxValue | ticks < long.MinValue || double.IsNaN(ticks))
+            {
+                throw new OverflowException(SR.Overflow_TimeSpanTooLong);
+            }
+
+            return FromTicks((long)ticks);
+        }
+
+        // Using floating-point arithmetic directly means that infinities can be returned, which is reasonable
+        // if we consider TimeSpan.FromHours(1) / TimeSpan.Zero asks how many zero-second intervals there are in
+        // an hour for which ∞ is the mathematic correct answer. Having TimeSpan.Zero / TimeSpan.Zero return NaN
+        // is perhaps less useful, but no less useful than an exception.
+        public static double operator /(TimeSpan t1, TimeSpan t2) => t1.Ticks / (double)t2.Ticks;
+
         public static bool operator ==(TimeSpan t1, TimeSpan t2)
         {
             return t1._ticks == t2._ticks;


Improve FlowContainer.Insert xmldoc

Improve FlowContainer.Insert xmldoc

--- osu.Framework/Graphics/Containers/FlowContainer.cs
+++ osu.Framework/Graphics/Containers/FlowContainer.cs
@@ -118,8 +118,8 @@
         /// <summary>
         /// Adds a child to this container and then set its layout position.
         /// </summary>
-        /// <param name="position">layout position of the new child</param>
-        /// <param name="drawable">drawable</param>
+        /// <param name="position">The layout position of the new child.</param>
+        /// <param name="drawable">The drawable which will be inserted into the container.</param>
         public void Insert(int position, T drawable)
         {
             Add(drawable);


formatting

formatting

--- osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs
+++ osu.Game.Rulesets.Catch/UI/CatchCursorContainer.cs
@@ -4,7 +4,8 @@
 using osu.Framework.Graphics;
 using osu.Game.Rulesets.UI;

-namespace osu.Game.Rulesets.Catch.UI {
+namespace osu.Game.Rulesets.Catch.UI
+{
     class CatchCursorContainer : GameplayCursorContainer
     {
         protected override Drawable CreateCursor() => new InvisibleCursor();


Nicefy the errormessage in the constructor of GetMessagesRequest

--- osu.Game/Online/API/Requests/GetMessagesRequest.cs
+++ osu.Game/Online/API/Requests/GetMessagesRequest.cs
@@ -18,7 +18,7 @@
             if (channels == null)
                 throw new ArgumentNullException(nameof(channels));
             if (channels.Any(c => c.Target != TargetType.Channel))
-                throw new ArgumentException($"All channels in the argument channels must have the {nameof(Channel.Target)} Channel");
+                throw new ArgumentException($"All channels in the argument channels must have a {nameof(Channel.Target)} of {nameof(TargetType.Channel)}");

             this.channels = channels;
         }


Compatibility in StringExtensions.

Compatibility in StringExtensions.

--- src/Tweetsharp.PCL/Extensions/StringExtensions.cs
+++ src/Tweetsharp.PCL/Extensions/StringExtensions.cs
@@ -36,12 +36,7 @@
             return entities;
         }

-        private const RegexOptions Options =
-#if !SILVERLIGHT
- RegexOptions.Compiled | RegexOptions.IgnoreCase;
-#else
-            RegexOptions.IgnoreCase;
-#endif
+        private const RegexOptions Options = RegexOptions.IgnoreCase;

         // Jon Gruber's URL Regex: http://daringfireball.net/2009/11/liberal_regex_for_matching_urls
         private static readonly Regex ParseUrls =


[packages,Python,3.6.1] Python library warning suppressions for clang

--- packages/Python-3.6.1/bam/Scripts/PythonLibrary.cs
+++ packages/Python-3.6.1/bam/Scripts/PythonLibrary.cs
@@ -259,6 +259,16 @@

             var objectSource = this.CreateCSourceContainer("$(packagedir)/Objects/*.c");
             objectSource.PrivatePatch(this.CoreBuildPatch);
+            objectSource.PrivatePatch(settings =>
+                {
+                    var clangCompiler = settings as ClangCommon.ICommonCompilerSettings;
+                    if (null != clangCompiler)
+                    {
+                        var compiler = settings as C.ICommonCompilerSettings;
+                        compiler.DisableWarnings.AddUnique("unused-function"); // Python-3.6.1/Objects/stringlib/find.h:46:1: error: unused function 'stringlib_find_slice' [-Werror,-Wunused-function]
+                        compiler.DisableWarnings.AddUnique("unused-parameter"); // Python-3.6.1/Objects/stringlib/find.h:46:61: error: unused parameter 'str_len' [-Werror,-Wunused-parameter]
+                    }
+                });

             objectSource["abstract.c"].ForEach(item =>
                 item.PrivatePatch(settings =>
@@ -372,6 +382,12 @@
                             var compiler = settings as C.ICommonCompilerSettings;
                             compiler.DisableWarnings.AddUnique("4244"); // Python-3.5.1\Objects\bytes_methods.c(297): warning C4244: '=': conversion from 'int' to 'char', possible loss of data
                         }
+                        var clangCompiler = settings as ClangCommon.ICommonCompilerSettings;
+                        if (null != clangCompiler)
+                        {
+                            var compiler = settings as C.ICommonCompilerSettings;
+                            compiler.DisableWarnings.AddUnique("missing-field-initializers"); // Python-3.6.1/Objects/bytes_methods.c:677:37: error: missing field 'len' initializer [-Werror,-Wmissing-field-initializers]
+                        }
                     }));
             objectSource["capsule.c"].ForEach(item =>
                 item.PrivatePatch(settings =>
@@ -933,6 +949,7 @@
                         {
                             var compiler = settings as C.ICommonCompilerSettings;
                             compiler.DisableWarnings.AddUnique("unused-parameter"); // Python-3.5.1/Objects/obmalloc.c:54:24: error: unused parameter 'ctx' [-Werror,-Wunused-parameter]
+                            clangCompiler.Pedantic = false; // Python-3.6.1/Objects/obmalloc.c:2114:66: error: format specifies type 'void *' but the argument has type 'const uint8_t *' (aka 'const unsigned char *') [-Werror,-Wformat-pedantic]
                         }
                     }));
             objectSource["odictobject.c"].ForEach(item =>
@@ -1510,6 +1527,7 @@
                         {
                             var compiler = settings as C.ICommonCompilerSettings;
                             compiler.DisableWarnings.AddUnique("unused-function"); // Python-3.5.1/Python/pylifecycle.c:181:1: error: unused function 'get_codec_name' [-Werror,-Wunused-function]
+                            compiler.DisableWarnings.AddUnique("unused-parameter"); // Python-3.6.1/Python/pylifecycle.c:1348:29: error: unused parameter 'fd' [-Werror,-Wunused-parameter]
                         }
                     }));

@@ -1599,6 +1617,7 @@
                         {
                             var compiler = settings as C.ICommonCompilerSettings;
                             compiler.DisableWarnings.AddUnique("missing-field-initializers"); // Python-3.5.1/Python/random.c:193:24: error: missing field 'st_dev' initializer [-Werror,-Wmissing-field-initializers]
+                            compiler.DisableWarnings.AddUnique("unused-parameter"); // Python-3.6.1/Python/random.c:465:46: error: unused parameter 'blocking' [-Werror,-Wunused-parameter]
                         }
                     }));

@@ -2541,6 +2560,7 @@
                         compiler.DisableWarnings.AddUnique("unused-parameter"); // Python-3.5.1/Modules/timemodule.c:38:21: error: unused parameter 'self' [-Werror,-Wunused-parameter]
                         compiler.DisableWarnings.AddUnique("missing-field-initializers"); // Python-3.5.1/Modules/timemodule.c:257:7: error: missing field 'doc' initializer [-Werror,-Wmissing-field-initializers]
                         compiler.DisableWarnings.AddUnique("overlength-strings"); // Python-3.5.1/Modules/timemodule.c:698:1: error: string literal of length 969 exceeds maximum length 509 that C90 compilers are required to support [-Werror,-Woverlength-strings]
+                        compiler.DisableWarnings.AddUnique("unused-function"); // Python-3.6.1/Modules/timemodule.c:1160:1: error: unused function 'get_zone' [-Werror,-Wunused-function]
                     }
                 });
             var _localemodule = builtinModuleSource.AddFiles("$(packagedir)/Modules/_localemodule.c");
@@ -2851,7 +2871,16 @@
                         compiler.DisableWarnings.AddUnique("missing-field-initializers"); // Python-3.5.1/Modules/_tracemalloc.c:1340:16: error: missing field 'ml_flags' initializer [-Werror,-Wmissing-field-initializers]
                     }
                 });
-            builtinModuleSource.AddFiles("$(packagedir)/Modules/hashtable.c"); // part of _tracemalloc
+            var hashtable = builtinModuleSource.AddFiles("$(packagedir)/Modules/hashtable.c"); // part of _tracemalloc
+            hashtable.First().PrivatePatch(settings =>
+                {
+                    var clangCompiler = settings as ClangCommon.ICommonCompilerSettings;
+                    if (null != clangCompiler)
+                    {
+                        var compiler = settings as C.ICommonCompilerSettings;
+                        compiler.DisableWarnings.AddUnique("unused-parameter"); // Python-3.6.1/Modules/hashtable.c:108:48: error: unused parameter 'ht' [-Werror,-Wunused-parameter]
+                    }
+                });
             var symtablemodule = builtinModuleSource.AddFiles("$(packagedir)/Modules/symtablemodule.c");
             symtablemodule.First().PrivatePatch(settings =>
                 {


fixed detection of project system

fixed detection of project system

--- src/VsExtension/Shell/InliningAnalyzerCommands.cs
+++ src/VsExtension/Shell/InliningAnalyzerCommands.cs
@@ -11,6 +11,7 @@
 using System.Windows.Forms;
 using EnvDTE;
 using Microsoft.VisualStudio.LanguageServices;
+using Microsoft.VisualStudio.ProjectSystem.Properties;
 using VsExtension.Shell.Runner;
 using Task = System.Threading.Tasks.Task;

@@ -283,7 +284,7 @@

         private static bool IsNewProjectFormat(Project vsProject)
         {
-            return vsProject.Kind == "{9A19103F-16F7-4668-BE54-9A1E7A4F7556}";
+            return vsProject is IVsBrowseObjectContext;
         }

         private TargetPlatform DetermineTargetPlatform(IProjectPropertyProvider propertyProvider)


Make sure we always have the right blend function for meshes

--- RenderOpenGl/RenderMeshToGl.cs
+++ RenderOpenGl/RenderMeshToGl.cs
@@ -112,6 +112,8 @@
 			{
 				GL.Color4(color.Red0To255, color.Green0To255, color.Blue0To255, color.Alpha0To255);

+				GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
+
 				if (color.Alpha0To1 < 1)
 				{
 					if (forceCullBackFaces)


housekeeping: Handle the DateTimeOffset cause where BSON data is already in Date. (#450)

Handle backwards compatibility case where data is already stored in the old format in the BSON format.

--- src/Akavache.Core/JsonDateTimeOffsetTickConverter.cs
+++ src/Akavache.Core/JsonDateTimeOffsetTickConverter.cs
@@ -19,6 +19,11 @@

         public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
         {
+            if (reader.TokenType == JsonToken.Date)
+            {
+                return (DateTimeOffset)reader.Value;
+            }
+
             var data = serializer.Deserialize<DateTimeOffsetData>(reader);

             if (data == null)


dont start animation until we have attached to visual tree.

--- src/Avalonia.Controls/TransitioningContentControl.cs
+++ src/Avalonia.Controls/TransitioningContentControl.cs
@@ -1,6 +1,7 @@
 using System;
 using System.Threading;
 using Avalonia.Animation;
+using Avalonia.Threading;

 namespace Avalonia.Controls;

@@ -18,7 +19,7 @@
     /// </summary>
     public static readonly StyledProperty<IPageTransition?> PageTransitionProperty =
         AvaloniaProperty.Register<TransitioningContentControl, IPageTransition?>(nameof(PageTransition),
-            new CrossFade(TimeSpan.FromSeconds(0.5)));
+            new CrossFade(TimeSpan.FromSeconds(0.125)));

     /// <summary>
@@ -46,13 +47,20 @@
         private set => SetAndRaise(DisplayedContentProperty, ref _displayedContent, value);
     }

+    protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
+    {
+        base.OnAttachedToVisualTree(e);
+
+        Dispatcher.UIThread.Post(() => UpdateContentWithTransition(Content));
+    }
+
     protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
     {
         base.OnPropertyChanged(change);

         if (change.Property == ContentProperty)
         {
-            UpdateContentWithTransition(Content);
+            Dispatcher.UIThread.Post(() => UpdateContentWithTransition(Content));
         }
     }

@@ -62,6 +70,11 @@
     /// <param name="content">New content to set.</param>
     private async void UpdateContentWithTransition(object? content)
     {
+        if (VisualRoot is null)
+        {
+            return;
+        }
+
         _lastTransitionCts?.Cancel();
         _lastTransitionCts = new CancellationTokenSource();


Fix Linux to not complain about command errors (BL-6769)

This is a temporary fix until we have time for a proper Linux
implementation.  Without it, annoying yellow crash dialogs always pop
up on Linux when editing a page with the Talking Book tool open.

--- src/BloomExe/web/controllers/AudioSegmentationApi.cs
+++ src/BloomExe/web/controllers/AudioSegmentationApi.cs
@@ -79,7 +79,7 @@

 		public bool AreAutoSegmentDependenciesMet(out string message)
 		{
-			if (DoesCommandCauseError("WHERE python", kWorkingDirectory))   // TODO: Linux compatability. Also more below.   Maybe use "locate" command on Linux?
+			if (DoesCommandCauseError("WHERE python", kWorkingDirectory))   // TODO: Linux compatability. Also more below.   Probably use "which" command on Linux.
 			{
 				message = "Python";
 				return false;
@@ -114,6 +114,12 @@
 		// Returns true if the command returned with an error
 		protected bool DoesCommandCauseError(string commandString, string workingDirectory, out string standardOutput, out string standardError, params int[] errorCodesToIgnore)
 		{
+			if (SIL.PlatformUtilities.Platform.IsLinux)
+			{
+				standardOutput = "";
+				standardError = "";
+				return true;	// TODO: Linux compatibility.
+			}
 			if (!String.IsNullOrEmpty(workingDirectory))
 			{
 				commandString = $"cd \"{workingDirectory}\" && {commandString}";


Trunk: Applied marcoamenola's patch to fix a bug with singleton modules. Closes issue 5158.

--- src/Caliburn.Core/Configuration/CaliburnFramework.cs
+++ src/Caliburn.Core/Configuration/CaliburnFramework.cs
@@ -193,7 +193,7 @@
                 if (!_moduleType.IsAssignableFrom(type) || type.IsAbstract || type.IsInterface)
                     continue;

-                var singleton = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static);
+                var singleton = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);

                 if (singleton != null)
                     modules.Add((IModule)singleton.GetValue(null, null));


Check if template is null

Check if template is null

--- src/Core2D/Renderer/Presenters/ContainerPresenter.cs
+++ src/Core2D/Renderer/Presenters/ContainerPresenter.cs
@@ -27,7 +27,11 @@
             var db = container.Data == null ? default(ImmutableArray<XProperty>) : container.Data.Properties;
             var r = container.Data == null ? default(XRecord) : container.Data.Record;

-            renderer.Draw(dc, container.Template, dx, dy, db, r);
+            if (container.Template != null)
+            {
+                renderer.Draw(dc, container.Template, dx, dy, db, r);
+            }
+
             renderer.Draw(dc, container, dx, dy, db, r);

             if (container.WorkingLayer != null)


Small extra check in an old state test

Small extra check in an old state test

--- ShieldedTests/OldStateTests.cs
+++ ShieldedTests/OldStateTests.cs
@@ -39,9 +39,11 @@
                 { 3, 3 },
             });
             Shield.InTransaction(() => {
+                Assert.AreEqual(1, dict[1]);
                 dict[2] = 102;
                 Assert.AreEqual(102, dict[2]);
                 Shield.ReadOldState(() => {
+                    Assert.AreEqual(1, dict[1]);
                     Assert.AreEqual(2, dict[2]);
                     var values = dict.Values;
                     Assert.AreEqual(3, values.Count);
@@ -49,8 +51,10 @@
                     dict[2] = 22;
                     Assert.AreEqual(2, dict[2]);
                 });
+                Assert.AreEqual(1, dict[1]);
                 Assert.AreEqual(22, dict[2]);
             });
+            Assert.AreEqual(1, dict[1]);
             Assert.AreEqual(22, dict[2]);
         }


Update SolrNet/Impl/ISolrQueryBody.cs

Update SolrNet/Impl/ISolrQueryBody.cs

Co-Authored-By: Gidon <2745efab5cd8ab271ae19247f1d7cceafc577547@gmail.com>

--- SolrNet/Impl/ISolrQueryBody.cs
+++ SolrNet/Impl/ISolrQueryBody.cs
@@ -13,7 +13,7 @@
         /// Convert the body into a string to send to Solr.
         /// </summary>
         /// <returns></returns>
-        string serialize();
+        string Serialize();

         /// <summary>
         /// The MimeType to use when sending the request.


+semver: minor

+semver: minor

--- Solution/NetStandard/Class1.cs
+++ Solution/NetStandard/Class1.cs
@@ -13,6 +13,6 @@
         // Second, Thirth
         public int FeaTwo { get; set; }
         // Rel One
-        // Minor.............
+        // Minor..............
     }
 }


opti compilation for NoArgsNewIntrinsic

opti compilation for NoArgsNewIntrinsic

--- src/FastExpressionCompiler/FastExpressionCompiler.cs
+++ src/FastExpressionCompiler/FastExpressionCompiler.cs
@@ -458,6 +458,17 @@
             return @delegate;
         }

+        private static Delegate CompileNoArgsNew(ConstructorInfo ctor, Type delegateType, Type[] closurePlusParamTypes, Type returnType)
+        {
+            var method = new DynamicMethod(string.Empty, returnType, closurePlusParamTypes, typeof(ArrayClosure), true);
+            var il = method.GetILGenerator(16); // 16 is enough for maximum of 3 possible ops
+            il.Emit(OpCodes.Newobj, ctor);
+            if (returnType == typeof(void))
+                il.Emit(OpCodes.Pop);
+            il.Emit(OpCodes.Ret);
+            return method.CreateDelegate(delegateType, EmptyArrayClosure);
+        }
+
 #if LIGHT_EXPRESSION
         internal static object TryCompileBoundToFirstClosureParam(Type delegateType, Expression bodyExpr, IParameterProvider paramExprs,
             Type[] closurePlusParamTypes, Type returnType, CompilerFlags flags)
@@ -466,6 +477,10 @@
             Type[] closurePlusParamTypes, Type returnType, CompilerFlags flags)
 #endif
         {
+#if LIGHT_EXPRESSION
+            if (bodyExpr is NoArgsNewClassIntrinsicExpression newNoArgs)
+                return CompileNoArgsNew(newNoArgs.Constructor, delegateType, closurePlusParamTypes, returnType);
+#endif
             var closureInfo = new ClosureInfo(ClosureStatus.ToBeCollected);
             if (!TryCollectBoundConstants(ref closureInfo, bodyExpr, paramExprs, false, ref closureInfo, flags))
                 return null;
@@ -498,12 +513,7 @@
             var method = new DynamicMethod(string.Empty, returnType, closurePlusParamTypes, typeof(ArrayClosure), true);

             // todo: @perf @mem the default stream capacity is 64, consider to decrease it to 16 for a member or no argument method
-#if LIGHT_EXPRESSION
-            var streamSize = bodyExpr is NoArgsNewClassIntrinsicExpression ? 16 : 64;
-#else
-            var streamSize = 64; // the default system value
-#endif
-            var il = method.GetILGenerator(streamSize);
+            var il = method.GetILGenerator(64);

             if (closure.ConstantsAndNestedLambdas != null)
                 EmittingVisitor.EmitLoadConstantsAndNestedLambdasIntoVars(il, ref closureInfo);
@@ -559,6 +569,7 @@
             return closureAndParamTypes;
         }

+        [MethodImpl((MethodImplOptions)256)]
         private static void ReturnClosureTypeToParamTypesToPool(Type[] closurePlusParamTypes)
         {
             var paramCount = closurePlusParamTypes.Length - 1;
@@ -1580,14 +1591,22 @@
                 return true;

             var nestedLambdaExpr = nestedLambdaInfo.LambdaExpression;
+            var nestedReturnType = nestedLambdaExpr.ReturnType;
+            var nestedLambdaBody = nestedLambdaExpr.Body;
+#if LIGHT_EXPRESSION
+            var nestedLambdaParamExprs = (IParameterProvider)nestedLambdaExpr;
+
+            if (nestedLambdaBody is NoArgsNewClassIntrinsicExpression newNoArgs)
+            {
+                var paramTypes = GetClosureTypeToParamTypes(nestedLambdaParamExprs);
+                nestedLambdaInfo.Lambda = CompileNoArgsNew(newNoArgs.Constructor, nestedLambdaExpr.Type, paramTypes, nestedReturnType);
+                ReturnClosureTypeToParamTypesToPool(paramTypes);
+                return true;
+            }
+#else
+            var nestedLambdaParamExprs = nestedLambdaExpr.Parameters;
+#endif
             ref var nestedClosureInfo = ref nestedLambdaInfo.ClosureInfo;
-
-#if LIGHT_EXPRESSION
-            var nestedLambdaParamExprs = (IParameterProvider)nestedLambdaExpr;
-#else
-            var nestedLambdaParamExprs = nestedLambdaExpr.Parameters;
-#endif
-
             var nestedLambdaNestedLambdaOrLambdas = nestedClosureInfo.NestedLambdaOrLambdas;
             if (nestedLambdaNestedLambdaOrLambdas != null)
             {
@@ -1614,7 +1633,6 @@
                     nestedLambdaClosure = new ArrayClosure(nestedClosureInfo.GetArrayOfConstantsAndNestedLambdas());
             }

-            var nestedReturnType = nestedLambdaExpr.ReturnType;
             var closurePlusParamTypes = GetClosureTypeToParamTypes(nestedLambdaParamExprs);

             var method = new DynamicMethod(string.Empty,
@@ -1627,7 +1645,7 @@
                 EmittingVisitor.EmitLoadConstantsAndNestedLambdasIntoVars(il, ref nestedClosureInfo);

             var parent = nestedReturnType == typeof(void) ? ParentFlags.IgnoreResult : ParentFlags.Empty;
-            if (!EmittingVisitor.TryEmit(nestedLambdaExpr.Body, nestedLambdaParamExprs, il, ref nestedClosureInfo, setup, parent))
+            if (!EmittingVisitor.TryEmit(nestedLambdaBody, nestedLambdaParamExprs, il, ref nestedClosureInfo, setup, parent))
                 return false;
             il.Emit(OpCodes.Ret);


Unit test modificictaions for Unity

Unit test modificictaions for Unity

--- unity/Assets/Editor/WhenAMessageIsPublished.cs
+++ unity/Assets/Editor/WhenAMessageIsPublished.cs
@@ -483,7 +483,7 @@
         }

         [Test]
-        [ExpectedException (typeof(MissingFieldException))]
+        [ExpectedException (typeof(MissingMemberException))]
         public void Then2PublishKeyShouldNotBeEmptyAfterOverriden ()
         {
             Pubnub pubnub = new Pubnub (
@@ -533,7 +533,7 @@
         }

         [Test]
-        [ExpectedException (typeof(MissingFieldException))]
+        [ExpectedException (typeof(MissingMemberException))]
         public void TestNullShouldBeTreatedAsEmpty ()
         {
             Pubnub pubnub = new Pubnub (


reduce caching duration

reduce caching duration

--- src/FilterLists.Api/V1/Controllers/BaseController.cs
+++ src/FilterLists.Api/V1/Controllers/BaseController.cs
@@ -5,13 +5,13 @@

 namespace FilterLists.Api.V1.Controllers
 {
-    [ApiVersion("1")]
+    [ApiVersion("1.0")]
     //TODO: use versioning without needing to manually specify in swagger-ui (https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/370)
     [Route("v{version:apiVersion}/[controller]")]
-    [ResponseCache(Duration = 86400)]
+    [ResponseCache(Duration = 14400)]
     public class BaseController : Controller
     {
-        protected static readonly TimeSpan MemoryCacheExpirationDefault = TimeSpan.FromDays(1);
+        protected static readonly TimeSpan MemoryCacheExpirationDefault = TimeSpan.FromHours(4);
         protected readonly IMemoryCache MemoryCache;
         protected readonly SeedService SeedService;


Added explicit ignores for object type, because changing the IsBaseType convention to something else makes the auto mapper pick up object as an entity

git-svn-id: a161142445158cf41e00e2afdd70bb78aded5464@230 48f0ce17-cc52-0410-af8c-857c09b6549b

--- src/FluentNHibernate/AutoMap/AutoPersistenceModel.cs
+++ src/FluentNHibernate/AutoMap/AutoPersistenceModel.cs
@@ -57,9 +57,7 @@
                         continue;
                 }

-                if (Conventions.IsBaseType(type))
-                    continue;
-                if (type.IsAbstract)
+                if (Conventions.IsBaseType(type) || type == typeof(object) || type.IsAbstract)
                     continue;

                 mappingTypes.Add(new AutoMapType(type));
@@ -101,7 +99,7 @@

         private Type GetTypeToMap(Type type)
         {
-            return Conventions.IsBaseType(type.BaseType) ? type : type.BaseType;
+            return Conventions.IsBaseType(type.BaseType) || type.BaseType == typeof(object) ? type : type.BaseType;
         }

         private void MergeMap(Type type, object mapping)


fixed a bug with our streamed TCP connections

--- src/Helios/Net/Connections/StreamedConnectionBase.cs
+++ src/Helios/Net/Connections/StreamedConnectionBase.cs
@@ -1,5 +1,6 @@
 using System;
 using System.IO;
+using System.Linq;
 using System.Net;
 using System.Threading.Tasks;
 using Helios.Net.Transports;
@@ -45,14 +46,14 @@
         {
             var memoryStream = new MemoryStream(1024);
             var buffer = Read(memoryStream.GetBuffer(), 0, (int)memoryStream.Length);
-            return NetworkData.Create(Node, memoryStream.GetBuffer(), (int)memoryStream.Capacity);
+            return NetworkData.Create(Node, memoryStream.GetBuffer().Take(buffer).ToArray(), buffer);
         }

         public async Task<NetworkData> RecieveAsync()
         {
             var memoryStream = new MemoryStream(1024);
             var buffer = await ReadAsync(memoryStream.GetBuffer(), 0, (int)memoryStream.Capacity);
-            return NetworkData.Create(Node, memoryStream.GetBuffer(),(int)memoryStream.Length);
+            return NetworkData.Create(Node, memoryStream.GetBuffer().Take(buffer).ToArray(), buffer);
         }

         public void Send(NetworkData payload)


typo in logout page

typo in logout page

--- src/IdentityServer4/host/Views/Account/Logout.cshtml
+++ src/IdentityServer4/host/Views/Account/Logout.cshtml
@@ -3,7 +3,7 @@

Logout

-
Would you like to logut of IdentityServer?

+
Would you like to logout of IdentityServer?

     <form asp-action="Logout">


fix: typo in error message when referenced CAB file is not embedded inside of the msi  (#168)

--- src/LessMsi.Core/Msi/ExternalCabNotFoundException.cs
+++ src/LessMsi.Core/Msi/ExternalCabNotFoundException.cs
@@ -12,7 +12,7 @@
     {
         public static ExternalCabNotFoundException CreateFromCabPath(string cabFileName, string expectedLocation)
         {
-            var msg = string.Format("This msi file references a CAB file that is not embedded inside of the msi file itself. The msi file is named {0} and was expected to be in the following folder: {1}", cabFileName, expectedLocation);
+            var msg = string.Format("This msi file references a CAB file that is not embedded inside of the msi file itself. The CAB file is named {0} and was expected to be in the following folder: {1}", cabFileName, expectedLocation);
             return new ExternalCabNotFoundException(msg);
         }


Lucene.Net.Core.Analysis.ReusableStringReader: Renamed private members to camelCase

--- src/Lucene.Net.Core/Analysis/ReusableStringReader.cs
+++ src/Lucene.Net.Core/Analysis/ReusableStringReader.cs
@@ -23,49 +23,49 @@
     /// Internal class to enable reuse of the string reader by <seealso cref="Analyzer#tokenStream(String,String)"/> </summary>
     public sealed class ReusableStringReader : System.IO.TextReader
     {
-        private int _pos = 0, _size = 0;
-        private string _s = null;
+        private int pos = 0, size = 0;
+        private string s = null;

         internal void SetValue(string s)
         {
-            this._s = s;
-            this._size = s.Length;
-            this._pos = 0;
+            this.s = s;
+            this.size = s.Length;
+            this.pos = 0;
         }

         public override int Read()
         {
-            if (_pos < _size)
+            if (pos < size)
             {
-                return _s[_pos++];
+                return s[pos++];
             }
             else
             {
-                _s = null;
+                s = null;
                 return -1;
             }
         }

         public override int Read(char[] c, int off, int len)
         {
-            if (_pos < _size)
+            if (pos < size)
             {
-                len = Math.Min(len, _size - _pos);
-                _s.CopyTo(_pos, c, off, _pos + len - _pos);
-                _pos += len;
+                len = Math.Min(len, size - pos);
+                s.CopyTo(pos, c, off, pos + len - pos);
+                pos += len;
                 return len;
             }
             else
             {
-                _s = null;
+                s = null;
                 return -1;
             }
         }

         protected override void Dispose(bool disposing)
         {
-            _pos = _size; // this prevents NPE when reading after close!
-            _s = null;
+            pos = size; // this prevents NPE when reading after close!
+            s = null;

             base.Dispose(disposing);
         }


теперь ещё и преподы в sitemap-е будут отображаться

--- src/MathSite.ViewModels/Home/HomeViewModelBuilder.cs
+++ src/MathSite.ViewModels/Home/HomeViewModelBuilder.cs
@@ -8,6 +8,7 @@
 using MathSite.Entities;
 using MathSite.Facades.Categories;
 using MathSite.Facades.Posts;
+using MathSite.Facades.Professors;
 using MathSite.Facades.SiteSettings;
 using MathSite.ViewModels.Home.EventPreview;
 using MathSite.ViewModels.Home.PostPreview;
@@ -23,6 +24,7 @@
         private readonly IEventPreviewViewModelBuilder _eventPreviewViewModelBuilder;
         private readonly IStudentActivityPreviewViewModelBuilder _activityPreviewViewModelBuilder;
         private readonly ICategoryFacade _categoryFacade;
+        private readonly IProfessorsFacade _professorsFacade;
         private readonly IPostPreviewViewModelBuilder _postPreviewViewModelBuilder;
         private readonly IPostsFacade _postsFacade;

@@ -32,7 +34,8 @@
             IPostPreviewViewModelBuilder postPreviewViewModelBuilder,
             IEventPreviewViewModelBuilder eventPreviewViewModelBuilder,
             IStudentActivityPreviewViewModelBuilder activityPreviewViewModelBuilder,
-            ICategoryFacade categoryFacade
+            ICategoryFacade categoryFacade,
+            IProfessorsFacade professorsFacade
         ) : base(siteSettingsFacade)
         {
             _postsFacade = postsFacade;
@@ -40,6 +43,7 @@
             _eventPreviewViewModelBuilder = eventPreviewViewModelBuilder;
             _activityPreviewViewModelBuilder = activityPreviewViewModelBuilder;
             _categoryFacade = categoryFacade;
+            _professorsFacade = professorsFacade;
         }

         public async Task<HomeIndexViewModel> BuildIndexModel()
@@ -114,6 +118,15 @@
             allNodes.AddRange(GetSitemapNodes(events));
             allNodes.AddRange(GetSitemapNodes(news));
             allNodes.AddRange(GetSitemapNodes(pages));
+
+            var professors = await _professorsFacade.GetProfessorsForPage(1, 50_000);
+
+            allNodes.AddRange(professors.Select(professor => new SitemapNode($"/professors/show/{professor.Id}")
+            {
+                ChangeFrequency = ChangeFrequency.Monthly,
+                Images = GetImages(professor.Person?.PhotoId?.ToString()),
+                Priority = 0.5M
+            }));

             return new SitemapModel(allNodes);
         }


- Add MaximumTimeInMinutes, which will cause the build task to quit after the specified time (default 10.0 mins)

- Add MaximumWorkspacesToClean to prevent taking on every workspace on the machine
- Remove usage of Robocopy (which can fail to return)

--- src/Microsoft.DotNet.Build.Tasks/CleanupVSTSAgent.cs
+++ src/Microsoft.DotNet.Build.Tasks/CleanupVSTSAgent.cs
@@ -7,6 +7,7 @@
 using System.Runtime.InteropServices;
 using System.Text.RegularExpressions;
 using System.Diagnostics;
+using System.Threading;

 namespace Microsoft.DotNet.Build.Tasks
 {
@@ -24,6 +25,10 @@

         public int? Retries { get; set; }

+        public double MaximumTimeInMinutes { get; set; } = 10;
+
+        public int MaximumWorkspacesToClean { get; set; } = 8;
+
         public int? SleepTimeInMilliseconds { get; set; }
         public ITaskItem[] ProcessNamesToKill { get; set; }

@@ -46,7 +51,23 @@
             {
                 SleepTimeInMilliseconds = s_DefaultSleepTime;
             }
-
+            bool returnValue = false;
+            Thread worker = new Thread(() => { returnValue = DoCleanupWork(); });
+            worker.Start();
+
+            if (worker.Join((int)TimeSpan.FromMinutes(MaximumTimeInMinutes).TotalMilliseconds))
+            {
+                return returnValue;
+            }
+            else
+            {
+                Log.LogWarning($" Cleanup Task ran for maximum time ({MaximumTimeInMinutes} minutes), aborting");
+                return false;
+            }
+        }
+
+        private bool DoCleanupWork()
+        {
             bool returnValue = true;

             if (Report)
@@ -55,7 +76,7 @@
             }
             if (Clean)
             {
-                returnValue &= CleanupDirsAsync().Result;
+                returnValue = CleanupDirsAsync().Result;
                 // If report and clean are both 'true', then report disk usage both before and after cleanup.
                 if (Report)
                 {
@@ -63,7 +84,6 @@
                     ReportDiskUsage();
                 }
             }
-
             return returnValue;
         }

@@ -234,7 +254,7 @@
             HashSet<string> knownDirectories = new HashSet<string>();
             List<System.Threading.Tasks.Task<bool>> cleanupTasks = new List<System.Threading.Tasks.Task<bool>>();

-            Log.LogMessage($"Found {sourceFolderJsons.Length} known agent working directories. ");
+            Log.LogMessage($"Found {sourceFolderJsons.Length} known agent working directories.  (Will clean up to {MaximumWorkspacesToClean} of them)");

             foreach (var sourceFolderJson in sourceFolderJsons)
             {
@@ -246,13 +266,21 @@

                 TimeSpan span = new TimeSpan(now.Ticks - agentInfo.Item3.Ticks);

-                if (span.TotalDays > RetentionDays)
-                {
-                    cleanupTasks.Add(CleanupAgentAsync(workDirectory, Path.GetDirectoryName(agentInfo.Item1)));
+                if (cleanupTasks.Count < MaximumWorkspacesToClean)
+                {
+                    if (span.TotalDays > RetentionDays)
+                    {
+                        cleanupTasks.Add(CleanupAgentAsync(workDirectory, Path.GetDirectoryName(agentInfo.Item1)));
+                    }
+                    else
+                    {
+                        Log.LogMessage($"Skipping cleanup for {sourceFolderJson}, it is newer than {RetentionDays} days old, last run date is '{agentInfo.Item3.ToString()}'");
+                    }
                 }
                 else
                 {
-                    Log.LogMessage($"Skipping cleanup for {sourceFolderJson}, it is newer than {RetentionDays} days old, last run date is '{agentInfo.Item3.ToString()}'");
+                    // We've taken enough cleanup tasks per the value of MaximumWorkspaces
+                    break;
                 }
             }

@@ -317,18 +345,6 @@
                 if (Directory.Exists(directory))
                 {
                     Log.LogMessage($"Attempting to cleanup {directory} ... ");
-
-                    // Unlike OSX and Linux, Windows has a hard limit of 260 chars on paths.
-                    // Some build definitions leave paths this long behind.  It's unusual,
-                    // but robocopy has been on Windows by default since XP and understands
-                    // how to stomp on long paths, so we'll use it to clean directories on Windows first.
-                    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
-                    {
-                        Log.LogMessage($"Preventing PathTooLongException by using robocopy to delete {directory} ");
-                        string emptyFolderToMirror = GetUniqueEmptyFolder();
-                        Process.Start(new ProcessStartInfo("robocopy.exe", $"/mir {emptyFolderToMirror} {directory}  /NJH /NJS /NP") { UseShellExecute = false }).WaitForExit();
-                        Directory.Delete(emptyFolderToMirror);
-                    }
                     Directory.Delete(directory, true);
                     Log.LogMessage("Success");
                 }
@@ -337,6 +353,12 @@
                     Log.LogMessage($"Specified directory, {directory}, does not exist");
                 }
                 return true;
+            }
+            catch (PathTooLongException)
+            {
+                // Theres no point in retrying for PathTooLong
+                Log.LogMessage($"Failed in cleanup attempt due to PathTooLongException, quitting.");
+                return false;
             }
             catch (Exception e)
             {


Review fixes #4

Review fixes #4

--- src/MiniCover/Commands/BaseCommandLineApplication.cs
+++ src/MiniCover/Commands/BaseCommandLineApplication.cs
@@ -43,7 +43,7 @@
             }
         }

-        private void InvalidateOptions()
+        private void ValidateOptions()
         {
             foreach (var miniCoverOption in MiniCoverOptions)
             {
@@ -55,7 +55,7 @@
         {
             OnExecute(() =>
             {
-                InvalidateOptions();
+                ValidateOptions();
                 Line($"Starting command: {Description}");
                 return Execution();
             });


Missed 'unique' specification on component mapping

SVN: 488784591515bd4cdaa016be4ec9b172dc4e7caf@5041

--- src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs
+++ src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs
@@ -1,4 +1,5 @@
 using System.Collections.Generic;
+using System.Linq;
 using NHibernate.Cfg.MappingSchema;
 using NHibernate.Mapping;
 using System;
@@ -117,7 +118,7 @@
 					System.Type reflectedClass = mappedClass == null ? null : GetPropertyType(componentMapping.Class, mappedClass, propertyName, componentMapping.Access);
 					BindComponent(componentMapping, value, reflectedClass, entityName, subpath, componetDefaultNullable, inheritedMetas);
 					property = CreateProperty(entityPropertyMapping, className, value, inheritedMetas);
-					BindComponentProperty(componentMapping, property);
+					BindComponentProperty(componentMapping, property, value);
 				}
 				else if ((oneToOneMapping = entityPropertyMapping as HbmOneToOne) != null)
 				{
@@ -134,7 +135,7 @@
 					System.Type reflectedClass = mappedClass == null ? null : GetPropertyType(dynamicComponentMapping.Class, mappedClass, propertyName, dynamicComponentMapping.Access);
 					BindComponent(dynamicComponentMapping, value, reflectedClass, entityName, subpath, componetDefaultNullable, inheritedMetas);
 					property = CreateProperty(entityPropertyMapping, className, value, inheritedMetas);
-					BindComponentProperty(dynamicComponentMapping, property);
+					BindComponentProperty(dynamicComponentMapping, property, value);
 				}
 				else if ((anyMapping = entityPropertyMapping as HbmAny) != null)
 				{
@@ -314,16 +315,24 @@
 			}
 		}

-		private void BindComponentProperty(HbmDynamicComponent dynamicComponentMapping, Property property)
+		private void BindComponentProperty(HbmDynamicComponent dynamicComponentMapping, Property property, Component model)
 		{
 			property.IsUpdateable = dynamicComponentMapping.update;
 			property.IsInsertable = dynamicComponentMapping.insert;
-		}
-
-		private void BindComponentProperty(HbmComponent componentMapping, Property property)
+			if (dynamicComponentMapping.unique)
+			{
+				model.Owner.Table.CreateUniqueKey(model.ColumnIterator.OfType<Column>().ToList());
+			}
+		}
+
+		private void BindComponentProperty(HbmComponent componentMapping, Property property, Component model)
 		{
 			property.IsUpdateable = componentMapping.update;
 			property.IsInsertable = componentMapping.insert;
+			if (componentMapping.unique)
+			{
+				model.Owner.Table.CreateUniqueKey(model.ColumnIterator.OfType<Column>().ToList());
+			}
 		}

 		private void BindManyToOneProperty(HbmManyToOne manyToOneMapping, Property property)


LevelService#AddLevelRole: Added debug message

--- src/NadekoBot/Modules/Level/Services/LevelService.cs
+++ src/NadekoBot/Modules/Level/Services/LevelService.cs
@@ -47,6 +47,8 @@
                 var level = uow.LevelModel.GetLevel(user.Id);
                 var userroles = user.GetRoles();
                 sm.Channel.SendMessageAsync("2").GetAwaiter().GetResult();
+                var rlbs = uow.RoleLevelBinding.GetAll();
+                sm.Channel.SendMessageAsync($"rlbs count: {rlbs.Count()}").GetAwaiter().GetResult();
                 var rlb = (from rl in uow.RoleLevelBinding.GetAll()
                            where rl.MinimumLevel <= level && userroles.All(r => r.Id != rl.RoleId) select rl) as List<RoleLevelBinding> ?? new List<RoleLevelBinding>();
                 sm.Channel.SendMessageAsync($"rlb count: {rlb?.Count}").GetAwaiter().GetResult();


add comment about possible elasticsearch bug on the get template call

--- src/Nest.Tests.Integration/Template/TemplateTests.cs
+++ src/Nest.Tests.Integration/Template/TemplateTests.cs
@@ -101,12 +101,13 @@
 					)
 				)
 			);
-			Assert.IsTrue(putResponse.OK);
+			Assert.IsTrue(putResponse.OK);

 			var templateResponse = this._client.GetTemplate("put-template-with-warmers");
 			templateResponse.Should().NotBeNull();
 			templateResponse.IsValid.Should().BeTrue();
 			templateResponse.TemplateMapping.Should().NotBeNull();
+			//possible elasticsearch bug https://github.com/elasticsearch/elasticsearch/issues/2868
 			templateResponse.TemplateMapping.Warmers.Should().NotBeNull().And.NotBeEmpty();
 		}
 	}


code cleanup

code cleanup

--- src/SimpleStack.Orm/Expressions/ExpressionVisitor.cs
+++ src/SimpleStack.Orm/Expressions/ExpressionVisitor.cs
@@ -21,10 +21,16 @@
         public virtual string VisitExpression(Expression exp)
         {
             var statement = Visit(exp);
+
+            if (statement == null)
+                return string.Empty;
+
             if (statement is ParameterPart pp)
                 return (bool) Parameters[pp.Text] ? "1=1" : "1=0";
+
             if (statement is ColumnAccessPart cp)
                 return $"{cp.Text} = {AddParameter(true)}";
+
             return statement.ToString();
         }

@@ -229,7 +235,10 @@

             var isIntegral = leftp != null && leftp.ParameterType != typeof(bool);

-            if (!isIntegral && rightp != null && rightp.ParameterType != typeof(bool)) isIntegral = true;
+            if (!isIntegral && rightp != null && rightp.ParameterType != typeof(bool))
+            {
+                isIntegral = true;
+            }

             var operand = DialectProvider.BindOperand(binaryExpression.NodeType, isIntegral);


No need to check against the target framework

As .NET Framework is based on .NET Standard, the GetTypeInfo method is available across all target frameworks for this package, so the checks are not necessary

--- src/Skybrud.Essentials/Reflection/ReflectionUtils.cs
+++ src/Skybrud.Essentials/Reflection/ReflectionUtils.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Diagnostics;
+using System.Linq;
 using System.Reflection;

 namespace Skybrud.Essentials.Reflection {
@@ -68,15 +69,7 @@
         /// <param name="type">The type to check.</param>
         /// <returns><c>true</c> if <paramref name="type"/> is a class type; otherwise <c>false</c>.</returns>
         public static bool IsClass(Type type) {
-
-#if NET_FRAMEWORK
-            return type.IsClass;
-#endif
-
-#if NET_STANDARD
             return type.GetTypeInfo().IsClass;
-#endif
-
         }

         /// <summary>
@@ -94,15 +87,7 @@
         /// <param name="type">The type to check.</param>
         /// <returns><c>true</c> if <paramref name="type"/> is an interface type; otherwise <c>false</c>.</returns>
         public static bool IsInterface(Type type) {
-
-#if NET_FRAMEWORK
-            return type.IsInterface;
-#endif
-
-#if NET_STANDARD
             return type.GetTypeInfo().IsInterface;
-#endif
-
         }

         /// <summary>
@@ -120,15 +105,7 @@
         /// <param name="type">The type to check.</param>
         /// <returns><c>true</c> if <paramref name="type"/> is an enum; otherwise <c>false</c>.</returns>
         public static bool IsEnum(Type type) {
-
-#if NET_FRAMEWORK
-            return type.IsEnum;
-#endif
-
-#if NET_STANDARD
             return type.GetTypeInfo().IsEnum;
-#endif
-
         }

     }


fixed a couple of CoreCLR tests

fixed a couple of CoreCLR tests

--- src/StructureMap.Testing/Graph/PluginFamilyTester.cs
+++ src/StructureMap.Testing/Graph/PluginFamilyTester.cs
@@ -150,8 +150,18 @@
             family.Instances.Any().ShouldBeFalse();
         }

-        public class DataTable { }
-        public class DataSet { }
+        public class DataTable : IServiceProvider {
+            public object GetService(Type serviceType)
+            {
+                throw new NotImplementedException();
+            }
+        }
+        public class DataSet : IServiceProvider {
+            public object GetService(Type serviceType)
+            {
+                throw new NotImplementedException();
+            }
+        }

         [Fact]
         public void add_type_works_if_the_concrete_type_can_be_cast_to_plugintype()


Use exception in CappedStringWriter

Use exception in CappedStringWriter

The use of `Assert.True` is problematic here as it's throwing an xunit
defined exception. In this case `TrueException`. This is problematic
because it's not serializable yet it is callable from within our
isolated test `AppDomain` instances.

In this case we should just be throwing an exception directly here.

--- src/Test/Utilities/Portable/FX/CappedStringWriter.cs
+++ src/Test/Utilities/Portable/FX/CappedStringWriter.cs
@@ -33,7 +33,7 @@

         private void CapReached()
         {
-            Assert.True(false, "Test produced more output than expected (" + _expectedLength + " characters). Is it in an infinite loop? Output so far:\r\n" + GetStringBuilder());
+            throw new Exception($"Test produced more output than expected ({_expectedLength} characters). Is it in an infinite loop? Output so far:\r\n{GetStringBuilder()}");
         }

         public override void Write(char value)


modifies some code changes to null check and not to use extension methods that require singleton access.

--- src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs
+++ src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs
@@ -52,7 +52,7 @@
                 .ForMember(display => display.Alias, expression => expression.Ignore())
                 .ForMember(display => display.Tabs, expression => expression.ResolveUsing(new TabsAndPropertiesResolver(applicationContext.Services.TextService)))
                 .ForMember(display => display.AllowedActions, expression => expression.ResolveUsing(
-                    new ActionButtonsResolver(new Lazy<IUserService>(() => applicationContext.Services.UserService))))
+                    new ActionButtonsResolver(new Lazy<IUserService>(() => applicationContext.Services.UserService), new Lazy<IContentService>(() => applicationContext.Services.ContentService))))
                 .AfterMap((content, display) => AfterMap(content, display, applicationContext.Services.DataTypeService, applicationContext.Services.TextService,
                     applicationContext.Services.ContentTypeService));

@@ -219,10 +219,14 @@
         private class ActionButtonsResolver : ValueResolver<IContent, IEnumerable<string>>
         {
             private readonly Lazy<IUserService> _userService;
-
-            public ActionButtonsResolver(Lazy<IUserService> userService)
-            {
+            private readonly Lazy<IContentService> _contentService;
+
+            public ActionButtonsResolver(Lazy<IUserService> userService, Lazy<IContentService> contentService)
+            {
+                if (userService == null) throw new ArgumentNullException("userService");
+                if (contentService == null) throw new ArgumentNullException("contentService");
                 _userService = userService;
+                _contentService = contentService;
             }

             protected override IEnumerable<string> ResolveCore(IContent source)
@@ -233,15 +237,22 @@
                     return Enumerable.Empty<string>();
                 }
                 var svc = _userService.Value;
+
+                string path;
+                if (source.HasIdentity)
+                    path = source.Path;
+                else
+                {
+                    var parent = _contentService.Value.GetById(source.ParentId);
+                    path = parent == null ? "-1" : parent.Path;
+                }

                 var permissions = svc.GetPermissionsForPath(
                         //TODO: This is certainly not ideal usage here - perhaps the best way to deal with this in the future is
                         // with the IUmbracoContextAccessor. In the meantime, if used outside of a web app this will throw a null
                         // refrence exception :(
                         UmbracoContext.Current.Security.CurrentUser,
-                        // Here we need to do a special check since this could be new content, in which case we need to get the permissions
-                        // from the parent, not the existing one otherwise permissions would be coming from the root since Id is 0.
-                        source.HasIdentity ? source.Path : source.Parent().Path)
+                        path)
                     .GetAllPermissions();

                 return permissions;


fixes tests

fixes tests

--- src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs
+++ src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs
@@ -110,6 +110,8 @@
         {
             protected override string ResolveCore(IContent source)
             {
+                if (source == null || source.Template == null) return null;
+
                 var alias = source.Template.Alias;

                 //set default template if template isn't set


test fix

test fix

--- src/CommitmentsV2/SFA.DAS.CommitmentsV2/Application/Commands/BulkUploadAddDraftApprenticeships/BulkUploadAddDraftApprenticeshipCommandHandler.cs
+++ src/CommitmentsV2/SFA.DAS.CommitmentsV2/Application/Commands/BulkUploadAddDraftApprenticeships/BulkUploadAddDraftApprenticeshipCommandHandler.cs
@@ -23,7 +23,7 @@
         private readonly ICohortDomainService _cohortDomainService;
         private readonly IMediator _mediator;
         private readonly IProviderCommitmentsDbContext _providerDbContext;
-        private readonly Dictionary<long, long> _cohortIds;
+        private readonly Dictionary<long, long> _employerAccountEmptycohortIds;

         public BulkUploadAddDraftApprenticeshipCommandHandler(
             ILogger<BulkUploadAddDraftApprenticeshipCommandHandler> logger,
@@ -37,7 +37,7 @@
             _cohortDomainService = cohortDomainService;
             _mediator = mediator;
             _providerDbContext = providerCommitmentsDbContext;
-            _cohortIds = new Dictionary<long, long>();
+            _employerAccountEmptycohortIds = new Dictionary<long, long>();
         }

         public async Task<GetBulkUploadAddDraftApprenticeshipsResponse> Handle(BulkUploadAddDraftApprenticeshipsCommand request, CancellationToken cancellationToken)
@@ -54,7 +54,13 @@
                 _logger.LogInformation($"Bulk upload - Added draft apprenticeship. Reservation-Id:{draftApprenticeship.ReservationId} Commitment-Id:{cohortId}");
             }

-            foreach (var cohortId in _cohortIds.Values)
+            var cohortIds = request.BulkUploadDraftApprenticeships
+                .Where(x => x.CohortId != null)
+                .Select(x => x.CohortId.Value)
+                .Union(_employerAccountEmptycohortIds.Values)
+                .Distinct();
+
+            foreach (var cohortId in cohortIds)
             {
                 var cohort = await _cohortDomainService.GetCohortDetails(cohortId, cancellationToken);
                 draftApprenticeshipsResponse.Add(cohort);
@@ -70,29 +76,24 @@

         private async Task<long> GetCohortId(BulkUploadAddDraftApprenticeshipRequest bulkUploadAddDraftApprenticeshipRequest, UserInfo user, CancellationToken cancellation)
         {
-            if (_cohortIds.ContainsKey(bulkUploadAddDraftApprenticeshipRequest.LegalEntityId.Value))
+            if (bulkUploadAddDraftApprenticeshipRequest.CohortId.HasValue)
             {
-                return _cohortIds.GetValueOrDefault(bulkUploadAddDraftApprenticeshipRequest.LegalEntityId.Value);
+                return bulkUploadAddDraftApprenticeshipRequest.CohortId.Value;
+            }
+            else if (_employerAccountEmptycohortIds.ContainsKey(bulkUploadAddDraftApprenticeshipRequest.LegalEntityId.Value))
+            {
+                return _employerAccountEmptycohortIds.GetValueOrDefault(bulkUploadAddDraftApprenticeshipRequest.LegalEntityId.Value);
             }
             else
             {
-                long cohortId;
-                if (bulkUploadAddDraftApprenticeshipRequest.CohortId.HasValue)
-                {
-                    cohortId = bulkUploadAddDraftApprenticeshipRequest.CohortId.Value;
-                }
-                else
-                {
-                    var accountLegalEntity = _providerDbContext.AccountLegalEntities
-                      .Include(x => x.Account)
-                      .Where(x => x.Id == bulkUploadAddDraftApprenticeshipRequest.LegalEntityId).First();
+                var accountLegalEntity = _providerDbContext.AccountLegalEntities
+                  .Include(x => x.Account)
+                  .Where(x => x.Id == bulkUploadAddDraftApprenticeshipRequest.LegalEntityId).First();

-                    var cohort = await _cohortDomainService.CreateEmptyCohort(bulkUploadAddDraftApprenticeshipRequest.ProviderId, accountLegalEntity.Account.Id, accountLegalEntity.Id, user, cancellation);
+                var cohort = await _cohortDomainService.CreateEmptyCohort(bulkUploadAddDraftApprenticeshipRequest.ProviderId, accountLegalEntity.Account.Id, accountLegalEntity.Id, user, cancellation);

-                    cohortId = cohort.Id;
-                }
-                _cohortIds.Add(bulkUploadAddDraftApprenticeshipRequest.LegalEntityId.Value, cohortId);
-                return cohortId;
+                _employerAccountEmptycohortIds.Add(bulkUploadAddDraftApprenticeshipRequest.LegalEntityId.Value, cohort.Id);
+                return cohort.Id;
             }
         }


Building Suffix Links

Building Suffix Links

--- SuffixTreePrototype/Program.cs
+++ SuffixTreePrototype/Program.cs
@@ -2,24 +2,31 @@
 {
     using System;
     using System.Collections.Generic;
+    using System.Diagnostics;
     using System.Text;

-    // Still O(m^3) - skip count trick as in page 101
-    class SuffixTree2
+    // Still O(m^3) - building suffix links
+    class SuffixTree4
     {
-        private SuffixTree2(string text)
+        private SuffixTree4(string text)
         {
             // Avoid direct construction
             this.text = text;
         }

-        public static SuffixTree2 Build(string text)
+        public static SuffixTree4 Build(string text)
+        {
+            SuffixTree4 result = new SuffixTree4(text);
+            result.BuildTree(text);
+            return result;
+        }
+
+        private void BuildTree(string text)
         {
             // Step 1: Build initial tree
-            SuffixTree2 result = new SuffixTree2(text);
-            result.rootNode = new SuffixTreeNode();
+            this.rootNode = new SuffixTreeNode();
             string suffix = text[0] + "";
-            result.rootNode.links.Add(suffix[0], new SuffixTreeLink { Start = 0, End = 1, child = new SuffixTreeNode() });
+            this.rootNode.links.Add(suffix[0], new SuffixTreeLink { Start = 0, End = 1, child = new SuffixTreeNode() });

             // Step 2: Basic extension loop
             for (int phase = 2; phase <= text.Length; phase++)
@@ -27,10 +34,9 @@
                 for (int j = 1; j <= phase; j++)
                 {
                     // Extension j is about adding the string x[j..phase] into the suffix tree
-                    result.Extend(text, j, phase);
-                }
-            }
-            return result;
+                    this.Extend(text, j, phase);
+                }
+            }
         }

         private void Extend(string text, int j, int phase)
@@ -69,6 +75,8 @@
                     }
                 }
             }
+
+            SuffixTreeNode newlyCreatedInternalNode = null;

             char characterToExtend = text[phase - 1];
             if (followingLink != null)
@@ -104,8 +112,7 @@
                         // Rule 2
                         int originalEnd = followingLink.End;
                         SuffixTreeNode originalChild = followingLink.child;
-
-                        followingLink.child = new SuffixTreeNode();
+                        newlyCreatedInternalNode = followingLink.child = new SuffixTreeNode();
                         followingLink.End = followingLink.Start + linkCursor;
                         followingLink.child.links.Add(text[followingLink.Start + linkCursor], new SuffixTreeLink { Start = followingLink.Start + linkCursor, End = originalEnd, child = originalChild });
                         followingLink.child.links.Add(characterToExtend, new SuffixTreeLink { Start = phase - 1, End = phase, child = new SuffixTreeNode() });
@@ -124,6 +131,27 @@
                     nodeCursor.links.Add(characterToExtend, new SuffixTreeLink { Start = phase - 1, End = phase, child = new SuffixTreeNode() });
                 }
             }
+
+            if (this.lastInternalNode != null)
+            {
+                if (followingLink != null)
+                {
+                    Debug.Assert(linkCursor == followingLink.Length(), "B) We should always end up in another node if we applied rule 2");
+                    this.lastInternalNode.SuffixLink = followingLink.child;
+                }
+                else
+                {
+                    this.lastInternalNode.SuffixLink = nodeCursor;
+                }
+
+                this.lastInternalNode = null;
+            }
+
+            if (newlyCreatedInternalNode != null)
+            {
+                this.lastInternalNode = newlyCreatedInternalNode;
+            }
+
         }

         private class SuffixTreeLink
@@ -153,6 +181,8 @@
         {
             public Dictionary<char, SuffixTreeLink> links = new Dictionary<char, SuffixTreeLink>();

+            public SuffixTreeNode SuffixLink { get; set; }
+
             internal void BuildString(string text, StringBuilder sb, int indent)
             {
                 foreach (var link in links)
@@ -172,6 +202,7 @@
         }

         private SuffixTreeNode rootNode;
+        private SuffixTreeNode lastInternalNode;
         private string text;
     }

@@ -179,7 +210,8 @@
     {
         static void Main(string[] args)
         {
-            Console.WriteLine(SuffixTree2.Build("Hello World"));
+            SuffixTree4 result = SuffixTree4.Build("xabxac");
+            Console.WriteLine(result);
         }
     }
 }


-Fixed wrong pagesize

-Fixed wrong pagesize

--- src/biz.dfch.CS.Appclusive.UI/Config/PortalConfig.cs
+++ src/biz.dfch.CS.Appclusive.UI/Config/PortalConfig.cs
@@ -23,7 +23,7 @@
 {
     public class PortalConfig
     {
-        private const int _pageSize = 2; //restricted to 45 due to paging problems with Appclusive.Core
+        private const int _pageSize = 45; //restricted to 45 due to paging problems with Appclusive.Core
         public static int Pagesize = _pageSize;

         /// <summary>