Beispiel #1
0
        public override bool Accept(IActivityMonitor m, DeletedDiff deletedDiff)
        {
            var matchingPath = DiffRoot.Paths.FirstOrDefault(path => deletedDiff.Path.StartsWith(path));

            if (matchingPath != null)
            {
                m.Debug($"Deleted file ({deletedDiff.Path}) matched with one of the DiffRoot '{DiffRoot.Name}' path: {matchingPath}");
                DeletedDiffs.Add(deletedDiff);
                return(true);
            }
            m.Debug($"Deleted file ({deletedDiff.Path}) did not match with any of the DiffRoot '{DiffRoot.Name}' paths.");
            return(false);
        }
Beispiel #2
0
        public override bool Accept(IActivityMonitor m, ModifiedDiff modifiedDiff)
        {
            var matchingPath = DiffRoot.Paths.FirstOrDefault(path => modifiedDiff.OldPath.StartsWith(path) || modifiedDiff.NewPath.StartsWith(path));

            if (matchingPath != null)
            {
                m.Debug($"Modified file ('{modifiedDiff.OldPath}'=>'{modifiedDiff.NewPath}') matched with one of the DiffRoot '{DiffRoot.Name}' path: {matchingPath}");
                ModifiedDiffs.Add(modifiedDiff);
                return(true);
            }
            m.Debug($"Modified file ('{modifiedDiff.OldPath}'=>'{modifiedDiff.NewPath}') did not match with any of the DiffRoot '{DiffRoot.Name}' paths.");
            return(false);
        }
Beispiel #3
0
        public void Setup(IActivityMonitor monitor)
        {
            using (monitor.OpenInfo($"Executing {_scripts.Count} script(s) on this Workstation."))
                using (var tempPS1 = new TemporaryFile("ps1"))
                {
                    bool             hasError         = false;
                    HashSet <EnvVar> currentVariables = null;
                    foreach (var o in _scripts)
                    {
                        if (hasError)
                        {
                            break;
                        }
                        switch (o)
                        {
                        case HashSet <EnvVar> v: currentVariables = v; break;

                        case ScriptLine script:
                        {
                            using (monitor.OpenTrace($"Executing script Type='{script.Type}', WorkingDir='{script.WorkingDir}', Arguments='{script.Arguments}', ContinueOnNonZeroExitCode='{script.ContinueOnNonZeroExitCode}'."))
                            {
                                monitor.Debug($"With EnvironmentVariables: {currentVariables?.Select( v => v.ToString() ).Concatenate()}.");
                                monitor.Debug(script.Script);
                                var variables = currentVariables?.Select(v => (v.Name, Environment.ExpandEnvironmentVariables(v.Value))).ToList()
                                                ?? new List <(string Name, string)>();
                                variables.Add(("CKLI_WORLD_MAPPING", _fileSystem.Root));

                                System.IO.File.WriteAllText(tempPS1.Path, script.Script);
                                if (!ProcessRunner.RunPowerShell(
                                        monitor,
                                        script.WorkingDir,
                                        tempPS1.Path,
                                        new[] { script.Arguments },
                                        stdErrorLevel: LogLevel.Warn,
                                        variables))
                                {
                                    hasError |= !script.ContinueOnNonZeroExitCode;
                                    if (!hasError)
                                    {
                                        monitor.Warn("ContinueOnNonZeroExitCode is true: error is ignored.");
                                    }
                                }
                            }
                            break;
                        }
                        }
                    }
                }
        }
Beispiel #4
0
        public DiffResult BuildDiffResult(IActivityMonitor m, List <Commit> commits)
        {
            var    commitsAndParents = commits.Select(s => (s, s.Parents.FirstOrDefault()));
            var    commitWithDiff    = commitsAndParents.Select(c => (c.s, _git.Diff.Compare <TreeChanges>(c.s.Tree, c.Item2.Tree))).ToList();
            Commit firstCommit       = commits.First();
            Commit lastCommit        = commits.Last();

            if (firstCommit.Committer.When < lastCommit.Committer.When)
            {
                throw new ArgumentException("Unchronological commits order.");
            }
            m.Debug($"Diffing between {firstCommit.Sha} and {lastCommit.Sha}");
            var fullDiff = _git.Diff.Compare <TreeChanges>(lastCommit.Tree, firstCommit.Tree);

            using (m.OpenDebug("Finding commits that impacted changes."))
            {
                using (m.OpenDebug("Caching changes"))
                {
                    foreach (TreeEntryChanges change in fullDiff)
                    {
                        switch (change.Status)
                        {
                        case ChangeKind.Unmodified:
                            m.Debug($"Skipping {change.Path} because: {change.Status}.");
                            continue;

                        case ChangeKind.Added:
                            RunOnBuilders(m, new AddedDiff(change.Path));
                            break;

                        case ChangeKind.Deleted:
                            RunOnBuilders(m, new DeletedDiff(change.Path));
                            break;

                        case ChangeKind.Renamed:
                        case ChangeKind.Modified:
                            RunOnBuilders(m, new ModifiedDiff(change.OldPath, change.Path));
                            break;

                        default:
                            throw new NotImplementedException();    //So it's actually used... i tought it would not.
                        }
                    }
                }
            }
            //all the commits are now cached.
            return(new DiffResult(true, _diffRootResultBuilders.Select(p => p.Result).ToList(), _others.Result));
        }
 void RegisterClassMapping(AutoServiceClassInfo c, ref bool success)
 {
     if (!c.IsRealObject)
     {
         Debug.Assert(c.MostSpecialized != null);
         RegisterMapping(c.ClassType, c.MostSpecialized, ref success);
         foreach (var s in c.Specializations)
         {
             RegisterClassMapping(s, ref success);
         }
     }
     else
     {
         _monitor.Debug($"Skipping '{c}' Service class mapping since it is a Real object.");
     }
 }
Beispiel #6
0
 public IDiffResult GetProjectsDiff(IActivityMonitor m)
 {
     if (!_diffsComputed)
     {
         m.Debug($"Computing diff for {Solution.Solution.Name}.");
         _diffsComputed = true;
         var diffRoots = Solution.Solution.GeneratedArtifacts.Select(g => new DiffRoot(g.Artifact.TypedName, g.Project.ProjectSources));
         _diffResult = _info._repository.GetDiff(m, PreviousVersionCommitSha, diffRoots);
     }
     return(_diffResult);
 }
Beispiel #7
0
 /// <summary>
 /// Logs potential errors. Returns true if no error occured, false on error.
 /// </summary>
 /// <param name="m"></param>
 /// <param name="res"></param>
 /// <returns>True on success, false on error.</returns>
 async Task <bool> LogErrors(IActivityMonitor m, HttpResponseMessage res)
 {
     if (res.StatusCode == HttpStatusCode.Unauthorized)
     {
         using (m.OpenError("Unauthorized Status Code"))
         {
             if (res.Headers.Contains("www-authenticate"))
             {
                 List <string> auth = res.Headers.GetValues("www-authenticate").ToList();
                 if (auth.Contains("ipaddress"))
                 {
                     m.Error("Login is not allowed from your IP address");
                 }
                 else if (auth.Contains("otp"))
                 {
                     m.Error("OTP required for authentication");
                 }
                 else
                 {
                     m.Error("Unable to authenticate, need: " + string.Join(", ", auth));
                 }
             }
             else
             {
                 if ((await res.Content.ReadAsStringAsync()).Contains("one-time pass"))
                 {
                     m.Error("OTP required for authentication.");
                 }
                 else
                 {
                     m.Error("Unknown error.");
                 }
             }
         }
         return(false);
     }
     if (!res.IsSuccessStatusCode)
     {
         using (m.OpenError($"Response status code is not a success code: '{res.ReasonPhrase}'."))
         {
             m.Trace(await res.Content.ReadAsStringAsync());
         }
         return(false);
     }
     else
     {
         m.Debug("Response status code is a success status code.");
     }
     return(true);
 }
Beispiel #8
0
            internal IEnumerable <XNode> Apply(XElement e)
            {
                using (Monitor.OpenDebug($"Applying reusables to {e.ToStringPath()}."))
                {
                    if (e.Name == "Reuse")
                    {
                        if (e.Elements().Any(c => c.Name != "Remove"))
                        {
                            Monitor.Error($"Reuse element {e.ToStringPath()} can not have children other than Remove.");
                            return(Array.Empty <XElement>());
                        }
                        string reusableName          = (string)e.AttributeRequired("Name");
                        IEnumerable <XNode> reusable = Find(reusableName, clone: true);
                        if (reusable == null)
                        {
                            Monitor.Error($"Unable to find reusable named '{reusableName}' from {e.ToStringPath()}.");
                            return(Array.Empty <XElement>());
                        }
                        Debug.Assert(reusable.OfType <XElement>().DescendantsAndSelf().Any(c => c.Name == "Reuse") == false);
                        Monitor.Debug($"Expanded reusable named '{reusableName}'.");

                        var reusedRoot = new XElement(e.Name, reusable);
                        var removeExpr = e.Elements().Select(r => (string)r.AttributeRequired("Target")).ToList();
                        foreach (var toRemove in removeExpr)
                        {
                            var removes = reusedRoot.XPathSelectElements(toRemove).ToList();
                            if (removes.Count == 0)
                            {
                                Monitor.Error($"No match found for Remove Target {toRemove} in Reuse {e.ToStringPath()}.");
                                return(Array.Empty <XElement>());
                            }
                            foreach (var r in removes)
                            {
                                r.Remove();
                            }
                        }
                        return(reusedRoot.Nodes());
                    }
                    var children = e.Nodes().SelectMany(n => n is XElement c ? Apply(c) : new[] { n.Clone() });
                    return(e.Name == "Reusable"
                                ? children
                                : new[] { new XElement(
                                              e.Name,
                                              e.Attributes().Select(a => a.Clone()),
                                              children).SetLineColumnInfo(e) });
                }
            }
Beispiel #9
0
        /// <summary>
        /// Gets infos on a package.
        /// The json format is available here: https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md
        /// </summary>
        /// <param name="m"></param>
        /// <param name="packageName">The package name</param>
        /// <param name="version">The info on the package on a specified versions, return a json containing the info of all the version if it's not specified</param>
        /// <param name="abbreviatedResponse">Ask the server to abreviate the info
        /// </param>
        /// <returns>The JSON response body and a success flag.</returns>
        public async Task <(string viewJson, bool exist)> View(IActivityMonitor m, string packageName, SVersion version = null, bool abbreviatedResponse = true)
        {
            if (version == null)
            {
                // We can't optimise it unless we know the fallback feed, and we can't know with azure because the api ask for a version.
                m.Debug("Getting all the versions of the package.");
                (string body, HttpStatusCode statusCode) = await ViewRequest(m, packageName, abbreviatedResponse);

                bool success = IsSuccessStatusCode(statusCode);
                if (!success)
                {
                    m.Warn($"Failed status code {statusCode} for '{RegistryUri}'.");
                }

                return(body, success);
            }
            // Here we know that the user specified the version
            return(await LegacyViewWithVersion(m, packageName, version, abbreviatedResponse));
        }
Beispiel #10
0
        static PocoRootInfo?CreateClassInfo(IDynamicAssembly assembly, IActivityMonitor monitor, IReadOnlyList <Type> interfaces)
        {
            // The first interface is the PrimartyInterface: we use its name to drive the implementation name.
            string pocoTypeName = assembly.GetAutoImplementedTypeName(interfaces[0]);
            var    moduleB      = assembly.StubModuleBuilder;
            var    tB           = moduleB.DefineType(pocoTypeName);

            // The factory also ends with "_CK": it is a generated type.
            var tBF = moduleB.DefineType(pocoTypeName + "Factory_CK");

            // The IPocoFactory base implementation.
            tBF.AddInterfaceImplementation(typeof(IPocoFactory));
            {
                MethodBuilder m = tBF.DefineMethod("get_PocoDirectory", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Final, typeof(PocoDirectory), Type.EmptyTypes);
                ILGenerator   g = m.GetILGenerator();
                g.Emit(OpCodes.Ldnull);
                g.Emit(OpCodes.Ret);
                var p = tBF.DefineProperty(nameof(IPocoFactory.PocoDirectory), PropertyAttributes.None, typeof(PocoDirectory), null);
                p.SetGetMethod(m);
            }
            {
                MethodBuilder m = tBF.DefineMethod("get_PocoClassType", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Final, typeof(Type), Type.EmptyTypes);
                ILGenerator   g = m.GetILGenerator();
                g.Emit(OpCodes.Ldtoken, tB);
                g.Emit(OpCodes.Call, _typeFromToken);
                g.Emit(OpCodes.Ret);
                var p = tBF.DefineProperty(nameof(IPocoFactory.PocoClassType), PropertyAttributes.None, typeof(Type), null);
                p.SetGetMethod(m);
            }
            {
                MethodBuilder m = tBF.DefineMethod("get_Name", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Final, typeof(string), Type.EmptyTypes);
                ILGenerator   g = m.GetILGenerator();
                g.Emit(OpCodes.Ldnull);
                g.Emit(OpCodes.Ret);
                var p = tBF.DefineProperty(nameof(IPocoFactory.Name), PropertyAttributes.None, typeof(string), null);
                p.SetGetMethod(m);
            }
            {
                MethodBuilder m = tBF.DefineMethod("get_PreviousNames", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Final, typeof(IReadOnlyList <string>), Type.EmptyTypes);
                ILGenerator   g = m.GetILGenerator();
                g.Emit(OpCodes.Ldnull);
                g.Emit(OpCodes.Ret);
                var p = tBF.DefineProperty(nameof(IPocoFactory.PreviousNames), PropertyAttributes.None, typeof(IReadOnlyList <string>), null);
                p.SetGetMethod(m);
            }
            {
                MethodBuilder m = tBF.DefineMethod("get_Interfaces", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Final, typeof(IReadOnlyList <Type>), Type.EmptyTypes);
                ILGenerator   g = m.GetILGenerator();
                g.Emit(OpCodes.Ldnull);
                g.Emit(OpCodes.Ret);
                var p = tBF.DefineProperty(nameof(IPocoFactory.Interfaces), PropertyAttributes.None, typeof(IReadOnlyList <Type>), null);
                p.SetGetMethod(m);
            }
            {
                MethodBuilder m = tBF.DefineMethod("Create", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.Final, typeof(IPoco), Type.EmptyTypes);
                ILGenerator   g = m.GetILGenerator();
                g.Emit(OpCodes.Ldnull);
                g.Emit(OpCodes.Ret);
            }

            // The IPocoGeneratedClass implementation.
            var properties   = new Dictionary <string, PocoPropertyInfo>();
            var propertyList = new List <PocoPropertyInfo>();
            List <PropertyInfo>?externallyImplementedPropertyList = null;

            // This is required to handle "non actual Poco" (CKTypeDefiner "base type"): interfaces list
            // contains only actual IPoco, the expanded set contains the closure of all the interfaces.
            //
            // This work is the perfect opportunity to handle the "closed poco" feature without overhead:
            // by identifying the "biggest" interface in terms of base interfaces, we can check that it
            // actually closes the whole IPoco.
            //
            var  expanded     = new HashSet <Type>(interfaces);
            Type?closure      = null;
            int  maxICount    = 0;
            bool mustBeClosed = false;

            foreach (var i in interfaces)
            {
                mustBeClosed |= typeof(IClosedPoco).IsAssignableFrom(i);
                var bases = i.GetInterfaces();
                if (closure == null || maxICount < bases.Length)
                {
                    maxICount = bases.Length;
                    closure   = i;
                }
                expanded.AddRange(bases);
                // Since we are iterating over the IPoco interfaces, we can build
                // the factory class that must support all the IPocoFactory<>.
                Type iCreate = typeof(IPocoFactory <>).MakeGenericType(i);
                tBF.AddInterfaceImplementation(iCreate);
                {
                    MethodBuilder m = tBF.DefineMethod("C" + expanded.Count.ToString(System.Globalization.NumberFormatInfo.InvariantInfo), MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.Final, i, Type.EmptyTypes);
                    ILGenerator   g = m.GetILGenerator();
                    g.Emit(OpCodes.Ldnull);
                    g.Emit(OpCodes.Ret);
                    tBF.DefineMethodOverride(m, iCreate.GetMethod(nameof(IPocoFactory <IPoco> .Create)) !);
                }
            }
            // If the IClosedPoco has been found, we ensure that a closure interface has been found.
            if (mustBeClosed)
            {
                Debug.Assert(maxICount < expanded.Count);
                if (maxICount < expanded.Count - 1)
                {
                    monitor.Error($"Poco family '{interfaces.Select( b => b.ToCSharpName() ).Concatenate("', '")}' must be closed but none of these interfaces covers the other ones.");
                    return(null);
                }
                Debug.Assert(closure != null, "Since there is at least one interface.");
                monitor.Debug($"{closure.FullName}: IClosedPoco for {interfaces.Select( b => b.ToCSharpName() ).Concatenate()}.");
            }
            // Supports the IPocoGeneratedClass interface.
            tB.AddInterfaceImplementation(typeof(IPocoGeneratedClass));
            {
                MethodBuilder m = tB.DefineMethod("get_Factory", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Final, typeof(IPocoFactory), Type.EmptyTypes);
                ILGenerator   g = m.GetILGenerator();
                g.Emit(OpCodes.Ldnull);
                g.Emit(OpCodes.Ret);
                var p = tB.DefineProperty(nameof(IPocoGeneratedClass.Factory), PropertyAttributes.None, typeof(IPocoFactory), null);
                p.SetGetMethod(m);
            }

            // For each expanded interfaces (all of them: the Interfaces and the OtherInterfaces):
            // - Implements the interface on the PocoClass (tB).
            // - Registers the properties and creates the PocoPropertyInfo.
            bool hasPropertyError = false;

            foreach (var i in expanded)
            {
                tB.AddInterfaceImplementation(i);

                // Analyzing interface properties.
                // For union types, the UnionTypes nested struct fields are cached once.
                PropertyInfo[]? unionTypesDef = null;

                foreach (var p in i.GetProperties())
                {
                    // As soon as a property claims to be implemented, we remove it from the properties.
                    if (p.GetCustomAttributesData().Any(d => d.AttributeType.Name == nameof(AutoImplementationClaimAttribute)))
                    {
                        if (externallyImplementedPropertyList == null)
                        {
                            externallyImplementedPropertyList = new List <PropertyInfo>();
                        }
                        externallyImplementedPropertyList.Add(p);
                        if (properties.TryGetValue(p.Name, out var implP))
                        {
                            propertyList.RemoveAt(implP.Index);
                            for (int idx = implP.Index; idx < propertyList.Count; ++idx)
                            {
                                --propertyList[idx].Index;
                            }
                        }
                    }
                    else
                    {
                        hasPropertyError &= HandlePocoProperty(monitor, expanded, properties, propertyList, ref unionTypesDef, i, p);
                    }
                }
            }
            if (hasPropertyError)
            {
                return(null);
            }

            // Implements the stubs for each externally implemented property.
            if (externallyImplementedPropertyList != null)
            {
                foreach (var p in externallyImplementedPropertyList)
                {
                    EmitHelper.ImplementStubProperty(tB, p, isVirtual: false, alwaysImplementSetter: false);
                }
            }

            // Handles default values and implements the stubs for each
            // PocoPropertyInfo.
            foreach (var p in propertyList)
            {
                if (!InitializeDefaultValue(p, monitor))
                {
                    return(null);
                }

                if (p.IsReadOnly && p.DefaultValueSource != null)
                {
                    monitor.Error($"Read only {p} cannot have a default value attribute: [DefaultValue( {p.DefaultValueSource} )].");
                    return(null);
                }
                foreach (var propInfo in p.DeclaredProperties)
                {
                    EmitHelper.ImplementStubProperty(tB, propInfo, isVirtual: false);
                }
            }

            var tPoCo = tB.CreateType();

            Debug.Assert(tPoCo != null);

            var tPocoFactory = tBF.CreateType();

            Debug.Assert(tPocoFactory != null);

            return(new PocoRootInfo(tPoCo, tPocoFactory, mustBeClosed, closure, expanded, properties, propertyList, externallyImplementedPropertyList));
        }
Beispiel #11
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="m"></param>
        /// <param name="solutions"></param>
        /// <param name="traceGraphDetails"></param>
        /// <param name="solutionCtx">May be null, used to construct the <see cref="DependencyAnalyzer"/></param>
        /// <returns></returns>
        internal static DependencyAnalyzer Create(IActivityMonitor m, IReadOnlyCollection <ISolution> solutions, bool traceGraphDetails, ISolutionContext solutionCtx)
        {
            var packages     = new Dictionary <Artifact, LocalPackageItem>();
            var projectItems = new ProjectItem.Cache();
            var externalRefs = new List <PackageReference>();

            // Note: Project to project references are translated into Requirements directly
            //       in the ProjectItem constructor.
            //       After having built the ProjectItem, we handle here the Packages (and PackageReferences between
            //       projects).
            using (m.OpenDebug("Creating all the ProjectItem for all projects in all solutions."))
            {
                foreach (var s in solutions)
                {
                    using (m.OpenDebug($"Solution {s.Name}."))
                    {
                        foreach (var project in s.Projects)
                        {
                            projectItems.Create(project);
                        }
                    }
                }
            }
            using (m.OpenDebug("Creating Package for all installable Artifacts in all solutions."))
            {
                foreach (var s in solutions)
                {
                    using (m.OpenDebug($"Solution {s.Name}."))
                    {
                        foreach (var project in s.Projects)
                        {
                            foreach (var package in project.GeneratedArtifacts.Where(a => a.Artifact.Type.IsInstallable))
                            {
                                if (packages.TryGetValue(package.Artifact, out var alreadyPublished))
                                {
                                    m.Error($"'{package.Project.Solution+"->"+package}' is already published by {alreadyPublished.Project.Solution+"->"+alreadyPublished.Project}.");
                                    return(null);
                                }
                                packages.Add(package.Artifact, new LocalPackageItem(package.Artifact, project));
                                m.Debug($"Package '{package}' created.");
                            }
                        }
                    }
                }
            }

            // 3 - Create the requirements between each project and Packages that are bound to a
            //     Published project (the LocalPackageItem previuosly created).
            //     When PackageReferences references external Packages, we add it to the ExternalRefs.
            foreach (var project in projectItems.AllProjectItems)
            {
                // Consider package references (Project to Project references are handled by ProjectItem constructors).
                foreach (var dep in project.Project.PackageReferences)
                {
                    if (packages.TryGetValue(dep.Target.Artifact, out LocalPackageItem target))
                    {
                        if (target.Project.Solution != project.Project.Solution)
                        {
                            project.AddRequires(target);
                        }
                        else
                        {
                            // A project is referencing a Package that is generated by
                            // its own Solution. This can happen (even if it is strange): for instance to test packages
                            // from the solution itself (the more correct way to do this is to use another
                            // Repository/Solution to test the packages since here you always test the "previous"
                            // package version).
                            //
                            // We transform the package reference into a project reference so that this edge
                            // case does not create cycles.
                            project.AddRequires(projectItems[target.Project]);
                        }
                    }
                    else
                    {
                        // Dependency to an external Package.
                        externalRefs.Add(dep);
                    }
                }
            }
            return(new DependencyAnalyzer(
                       m,
                       solutions,
                       solutionCtx,
                       projectItems,
                       externalRefs,
                       traceGraphDetails));
        }
Beispiel #12
0
        /// <summary>
        /// Publish a package to the repository
        /// </summary>
        /// <param name="m"></param>
        /// <param name="packageJson">The package.json of the package to push</param>
        /// <param name="tarball">This stream must be Seek-able. <see cref="Stream"/> of the tarball of the package to push.</param>
        /// <param name="distTag"></param>
        /// <returns></returns>
        public bool Publish(IActivityMonitor m, NormalizedPath tarballPath, bool isPublic, string scope = null, string distTag = null)
        {
            if (RegistryUri.IsFile)
            {
                var path = Path.Combine(RegistryUri.AbsolutePath, tarballPath.LastPart);
                if (File.Exists(path))
                {
                    return(true);
                }
                try
                {
                    File.Copy(tarballPath, path);
                    return(true);
                }
                catch (Exception e)
                {
                    m.Error(e);
                }
                return(false);
            }
            string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());

            using (m.OpenInfo("Using 'npm publish'."))
            {
                try
                {
                    Directory.CreateDirectory(tempDirectory);
                    m.Debug($"Creating temp directory {tempDirectory}.");
                    using (m.OpenInfo("Creating .npmrc with content:"))
                        using (StreamWriter w = File.CreateText(Path.Combine(tempDirectory, ".npmrc")))
                        {
                            string uriString = RegistryUri.ToString();
                            w.WriteLine($"registry={uriString}");
                            m.Debug($"registry={uriString}");
                            string uriConfig = uriString.Remove(0, uriString.IndexOf('/'));

                            if (_authHeader == null)
                            {
                                m.Error("Missing credentials to configure .npmrc file.");
                                return(false);
                            }
                            if (_authHeader.Scheme == "Basic")
                            {
                                w.WriteLine($"{uriConfig}:always-auth=true");
                                m.Debug($"{uriConfig}:always-auth=true");

                                w.WriteLine($"{uriConfig}:_password={Convert.ToBase64String( Encoding.UTF8.GetBytes( _password ) )}");
                                m.Debug($"{uriConfig}:_password=[REDACTED]");

                                w.WriteLine($"{uriConfig}:username={_username}");
                                m.Debug($"{uriConfig}:username={_username}");
                            }
                            else if (_authHeader.Scheme == "Bearer")
                            {
                                w.WriteLine($"{uriConfig}:always-auth=true");
                                m.Debug($"{uriConfig}:always-auth=true");
                                w.WriteLine($"{uriConfig}:_authToken={_authHeader.Parameter}");
                                m.Debug($"{uriConfig}:_authToken=[REDACTED]");
                            }

                            if (!string.IsNullOrWhiteSpace(scope))
                            {
                                w.WriteLine(scope + $":registry={RegistryUri.ToString()}");
                                m.Debug(scope + $":registry={RegistryUri.ToString()}");
                            }
                        }
                    string tarPath    = Path.GetFullPath(tarballPath);
                    string distTagArg = distTag != null ? $"--tag {distTag.ToLowerInvariant()}" : "";
                    string access     = isPublic ? "public" : "private";
                    if (Environment.OSVersion.Platform != PlatformID.Win32NT)
                    {
                        throw new PlatformNotSupportedException("Linux not supported yet.");
                    }
                    return(ProcessRunner.Run(m, tempDirectory, "cmd.exe", $"/C npm publish \"{tarPath}\" --access {access} {distTagArg}", LogLevel.Info));
                }
                catch (Exception ex)
                {
                    m.Error(ex);
                    return(false);
                }
                finally
                {
                    try
                    {
                        Directory.Delete(tempDirectory, true);
                    }
                    catch (Exception ex)
                    {
                        m.Warn($"While destroying temporary folder: {tempDirectory}", ex);
                    }
                }
            }
        }
        PocoJsonPropertyInfo?HandleUnionType(IPocoPropertyInfo p,
                                             IActivityMonitor monitor,
                                             JsonSerializationCodeGen jsonCodeGen,
                                             ITypeScopePart write,
                                             ITypeScopePart read,
                                             ref bool isPocoECMAScriptStandardCompliant,
                                             JsonCodeGenHandler mainHandler)
        {
            // Analyses the UnionTypes and creates the handler for each of them.
            // - Forbids ambiguous mapping for ECMAScriptStandard: all numerics are mapped to "Number" or "BigInt" (and arrays or lists are arrays).
            // - The ECMAScriptStandard projected name must be unique (and is associated to its actual handler).
            // -
            var allHandlers = new List <JsonCodeGenHandler>();
            var checkDuplicatedStandardName = new Dictionary <string, List <JsonCodeGenHandler> >();

            // Gets all the handlers and build groups of ECMAStandardJsnoName handlers (only if the Poco is still standard compliant).
            foreach (var union in p.PropertyUnionTypes)
            {
                var h = jsonCodeGen.GetHandler(union);
                if (h == null)
                {
                    return(null);
                }
                allHandlers.Add(h);
                if (isPocoECMAScriptStandardCompliant && h.HasECMAScriptStandardJsonName)
                {
                    var n = h.ECMAScriptStandardJsonName;
                    if (checkDuplicatedStandardName.TryGetValue(n.Name, out var exists))
                    {
                        exists.Add(h);
                    }
                    else
                    {
                        checkDuplicatedStandardName.Add(n.Name, new List <JsonCodeGenHandler>()
                        {
                            h
                        });
                    }
                }
            }
            allHandlers.Sort((h1, h2) => h1.TypeInfo.TypeSpecOrder.CompareTo(h2.TypeInfo.TypeSpecOrder));

            // Analyze the groups (only if the Poco is still standard compliant).
            List <JsonCodeGenHandler>?ecmaStandardReadhandlers = null;
            bool isECMAScriptStandardCompliant = isPocoECMAScriptStandardCompliant;

            if (isECMAScriptStandardCompliant)
            {
                foreach (var group in checkDuplicatedStandardName.Values)
                {
                    if (group.Count > 1)
                    {
                        int idxCanocical = group.IndexOf(h => h.ECMAScriptStandardJsonName.IsCanonical);
                        if (idxCanocical == -1)
                        {
                            monitor.Warn($"{p} UnionType '{group.Select( h => h.GenCSharpName ).Concatenate( "' ,'" )}' types mapped to the same ECMAScript standard name: '{group[0].ECMAScriptStandardJsonName.Name}' and none of them is the 'Canonical' form. De/serializing this Poco in 'ECMAScriptstandard' will throw a NotSupportedException.");
                            isECMAScriptStandardCompliant = false;
                            break;
                        }
                        var winner = group[idxCanocical];
                        monitor.Trace($"{p} UnionType '{group.Select( h => h.GenCSharpName ).Concatenate( "' ,'" )}' types will be read as {winner.GenCSharpName} in ECMAScript standard name.");
                        if (ecmaStandardReadhandlers == null)
                        {
                            ecmaStandardReadhandlers = allHandlers.Where(h => !h.HasECMAScriptStandardJsonName).ToList();
                        }
                        ecmaStandardReadhandlers.Add(winner);
                    }
                    else
                    {
                        monitor.Debug($"{p} UnionType unambiguous mapping in ECMAScript standard name from '{group[0].ECMAScriptStandardJsonName.Name}' to '{group[0].GenCSharpName}'.");
                        if (ecmaStandardReadhandlers == null)
                        {
                            ecmaStandardReadhandlers = allHandlers.Where(h => !h.HasECMAScriptStandardJsonName).ToList();
                        }
                        ecmaStandardReadhandlers.Add(group[0]);
                    }
                }
                isPocoECMAScriptStandardCompliant &= isECMAScriptStandardCompliant;
            }
            // Invariant: handlers are by design associated to different "oblivious NRT" types: switch case can be done on them.
            // That means that the actual's object type is enough to identify the exact handler (in THE CONTEXT of this property type!).
            // And the property setter controls the assignation: the set of types is controlled.
            //
            // It is tempting to simply call the generic write function but this one uses the GenericWriteHandler that is the "oblivious NRT" type:
            // even if this union exposes a ISet<string>? (nullable of non-nullable), it will be a ISet<string?> (non-nullable - since the GenericWriteHandler
            // is by design a NonNullHandler - of nullable - that is the oblivious nullability for reference type) that will be serialized.
            //
            // Actually the type name doesn't really matter, it's just a convention that a client must follow to receive or send data: here, we could
            // perfectly use the index of the type in the union types, that would be an identifier "local to this property" but this would do the job.
            //
            // What really matters is to identify the function that will read the data with the right null handling so that no nulls can be
            // injected where it should not AND to use the right function to write the data, the one that will not let unexpected nulls emitted.
            // Regarding this, using the GenericWriteHandler is definitely not right.
            //
            // That's why we generate a dedicated switch-case for writing here. If one of the handler is bound to the ObjectType (currently
            // that's true when jsonTypeInfo.IsFinal is false), we call the generic write object in the default: case.
            //
            Debug.Assert(!allHandlers.Select(h => h.TypeInfo.GenCSharpName).GroupBy(Util.FuncIdentity).Any(g => g.Count() > 1));

            var info = new PocoJsonPropertyInfo(p, allHandlers, isECMAScriptStandardCompliant ? ecmaStandardReadhandlers : null);

            _finalReadWrite.Add(() =>
            {
                var fieldName = "_v" + info.PropertyInfo.Index;
                write.Append("w.WritePropertyName( ").AppendSourceString(info.PropertyInfo.PropertyName).Append(" );").NewLine();
                if (info.IsJsonUnionType)
                {
                    write.GeneratedByComment()
                    .Append(@"switch( ").Append(fieldName).Append(" )")
                    .OpenBlock()
                    .Append("case null: ");
                    if (info.PropertyInfo.IsNullable)
                    {
                        write.Append("w.WriteNullValue();").NewLine()
                        .Append("break;");
                    }
                    else
                    {
                        write.Append(@"throw new InvalidOperationException( ""A null value appear where it should not. Writing JSON is impossible."" );");
                    }
                    write.NewLine();
                    bool hasDefaultObject = false;
                    foreach (var h in info.AllHandlers)
                    {
                        Debug.Assert(!h.IsNullable, "Union types are not nullable by design (null has been generalized).");
                        if (h.TypeInfo.IsFinal)
                        {
                            write.Append("case ").Append(h.TypeInfo.MostAbstractMapping?.GenCSharpName ?? h.TypeInfo.GenCSharpName).Append(" v: ").NewLine();
                            h.DoGenerateWrite(write, "v", handleNull: false, writeTypeName: true);
                            write.NewLine().Append("break;").NewLine();
                        }
                        else
                        {
                            hasDefaultObject = true;
                        }
                    }
                    write.Append(@"default:").NewLine();
                    if (hasDefaultObject)
                    {
                        mainHandler.ToNonNullHandler().GenerateWrite(write, fieldName);
                        write.NewLine().Append("break;");
                    }
                    else
                    {
                        write.Append(@"throw new InvalidOperationException( $""Unexpected type {").Append(fieldName).Append(@".GetType()} in union ").Append(info.PropertyInfo.ToString() !).Append(@"."" );");
                    }
                    write.CloseBlock();
                }
                else
                {
                    info.AllHandlers[0].GenerateWrite(write, fieldName);
                }

                read.Append("case ").AppendSourceString(info.PropertyInfo.PropertyName).Append(": ")
                .OpenBlock();

                if (info.IsJsonUnionType)
                {
                    read.Append("if( r.TokenType == System.Text.Json.JsonTokenType.Null )");
                    if (info.PropertyInfo.IsNullable)
                    {
                        read.OpenBlock()
                        .Append(fieldName).Append(" = null;").NewLine()
                        .Append("r.Read();")
                        .CloseBlock()
                        .Append("else")
                        .OpenBlock();
                    }
                    else
                    {
                        read.Append(" throw new System.Text.Json.JsonException(\"").Append(info.PropertyInfo.ToString() !).Append(" cannot be null.\");").NewLine();
                    }

                    if (info.IsJsonUnionType)
                    {
Beispiel #14
0
        void OnTime(object state)
        {
            // This is a simple lock that is non reentrant.
            // One may perfectly have used a standard .Net lock object here (Monitor.Enter/Exit) but
            // this is lighter than standard lock (since we don't want to wait to enter the lock, we just want to
            // skip the run).
            if (Interlocked.CompareExchange(ref _reentrancyFlag, 1, 0) == 0)
            {
                HandleDirtyOption();
                using (_monitor.OpenInfo($"Work n°{++_workCount}."))
                {
                    switch (_workCount % 16)
                    {
                    case 0: _monitor.Debug("A debug line (most verbose level)."); break;

                    case 1: _monitor.Trace("A trace line."); break;

                    case 2: _monitor.Info("An info line."); break;

                    case 3: _monitor.Warn("A warning line."); break;

                    case 4: _monitor.Error("An error line."); break;

                    case 5: _monitor.Fatal("A fatal line (most severe level)."); break;

                    case 6:
                    {
                        _monitor.Info(@"This would crash the entire process: throw new Exception( ""Unhandled exception, directly on the thread pool, during the timer handling."" ); ");
                        _monitor.Debug(@"
My first idea was that such an exception directly on the timer thread would have been trapped by AppDomain.CurrentDomain.UnhandledException. This is not the case:
see the (closed) issue: https://github.com/dotnet/extensions/issues/1836

""
The application exits because entire process is crashing. The host isn't gracefully shutting down, the process is just dying.
This happens when using timers or the thread pool directly without a try catch.
""
");
                        break;
                    }

                    case 7:
                    {
                        if (_options.CurrentValue.ThrowTaskSchedulerUnobservedTaskException)
                        {
                            _monitor.Trace(@"Calling: Task.Run( () => throw new Exception( ""Unhandled exception on the default Task scheduler."" ) );

This 'lost' exception will be hooked by a TaskScheduler.UnobservedTaskException an logged... but at the next GC time!
");
                            Task.Run(() => throw new Exception("Unhandled exception on the default Task scheduler."));
                        }
                        else
                        {
                            _monitor.Trace(@"Throwing unhandled exception has been skipped since ThrowTaskSchedulerUnobservedTaskException is false.");
                        }
                        break;
                    }

                    case 8:
                    {
                        if (_dotNetLogger == null)
                        {
                            _monitor.Info("Creating the '.Net Standard Demo' logger (this case n°8 emits a .Net LogTrace below).");
                            _dotNetLogger = _dotNetLoggerFactory.CreateLogger(".Net Standard Demo");
                        }
                        _dotNetLogger.LogTrace($".Net LogTrace (most verbose .Net log level).");
                        break;
                    }

                    case 9: _dotNetLogger.LogDebug($".Net LogDebug (Debug is less verbose than Trace fo .Net logs)."); break;

                    case 10: _dotNetLogger.LogInformation($".Net LogInformation."); break;

                    case 11: _dotNetLogger.LogWarning($".Net LogWarning."); break;

                    case 12: _dotNetLogger.LogError($".Net LogError."); break;

                    case 13: _dotNetLogger.LogCritical($".Net LogCritical (most severe .Net level)."); break;

                    case 14:
                    {
                        CheckSafeFailFast(() =>
                            {
                                Debug.Assert(false, "Debug.Assert failure results in a CK.Monitoring.MonitoringFailFastException and not a fail fast of the application.");
                            });

                        CheckSafeFailFast(() =>
                            {
                                Trace.Assert(false, "Trace.Assert failure results in a CK.Monitoring.MonitoringFailFastException and not a fail fast of the application.");
                            });

                        void CheckSafeFailFast(Action a)
                        {
                            try
                            {
                                a();
                            }
                            catch (CK.Monitoring.MonitoringFailFastException ex)
                            {
                                _monitor.Info($"Received a MonitoringFailFastException with message: {ex.Message}");
                            }
                        }

                        break;
                    }

                    default:
                        using (_monitor.OpenInfo("Calling the Garbage collector: this will release the TaskScheduler.UnobservedTaskException."))
                        {
                            GC.Collect();
                            _monitor.Trace("Waiting for completion.");
                            GC.WaitForFullGCComplete();
                        }
                        break;
                    }
                }
                HandleDirtyOption();
                Interlocked.Exchange(ref _reentrancyFlag, 0);
            }
        }
Beispiel #15
0
 public void LogDebug(string data)
 {
     lock (_lock) Monitor.Debug($"NuGet: {data}");
 }
        void OnTime(object state)
        {
            // This is a simple lock that is non reentrant.
            // One may perfectly have used a standard .Net lock object here (Monitor.Enter/Exit) but
            // this is even lighter than standard lock.
            if (Interlocked.CompareExchange(ref _reentrancyFlag, 1, 0) == 0)
            {
                HandleDirtyOption();
                using (_monitor.OpenInfo($"Work n°{++_workCount}."))
                {
                    switch (_workCount % 15)
                    {
                    case 0: _monitor.Debug("A debug line (most verbose level)."); break;

                    case 1: _monitor.Trace("A trace line."); break;

                    case 2: _monitor.Info("An info line."); break;

                    case 3: _monitor.Warn("A warning line."); break;

                    case 4: _monitor.Error("An error line."); break;

                    case 5: _monitor.Fatal("A fatal line (most severe level)."); break;

                    case 6:
                    {
                        _monitor.Info(@"throw new Exception( ""Unhandled exception, directly on the thread pool, during the timer handling."" );

My first idea was that such an exception directly on the timer thread would have been trapped by AppDomain.CurrentDomain.UnhandledException. This was not the case:
see the (still opened) issue: https://github.com/dotnet/extensions/issues/1836

""
The application exits because entire process is crashing. The host isn't gracefully shutting down, the process is just dying.
This happens when using timers or the thread pool directly without a try catch.
""
");
                        break;
                    }

                    case 7:
                    {
                        _monitor.Trace(@"Calling: Task.Run( () => throw new Exception( ""Unhandled exception on the default Task scheduler."" ) );

This 'lost' exception will be hooked by a TaskScheduler.UnobservedTaskException an logged... but at the next GC time!
");
                        Task.Run(() => throw new Exception("Unhandled exception on the default Task scheduler."));
                        break;
                    }

                    case 8:
                    {
                        if (_dotNetLogger == null)
                        {
                            _monitor.Info("Creating the '.Net Standard Demo' logger (this case n°8 emits a .Net LogTrace below).");
                            _dotNetLogger = _dotNetLoggerFactory.CreateLogger(".Net Standard Demo");
                        }
                        _dotNetLogger.LogTrace($".Net LogTrace (most verbose .Net log level).");
                        break;
                    }

                    case 9: _dotNetLogger.LogDebug($".Net LogDebug (Debug is less verbose than Trace fo .Net logs)."); break;

                    case 10: _dotNetLogger.LogInformation($".Net LogInformation."); break;

                    case 11: _dotNetLogger.LogWarning($".Net LogWarning."); break;

                    case 12: _dotNetLogger.LogError($".Net LogError."); break;

                    case 13: _dotNetLogger.LogCritical($".Net LogCritical (most severe .Net level)."); break;

                    default:
                        using (_monitor.OpenInfo("Calling the Garbage collector: this will release the Task.UnobservedExceptions."))
                        {
                            GC.Collect();
                            _monitor.Trace("Waiting for completion.");
                            GC.WaitForFullGCComplete();
                        }
                        break;
                    }
                }
                HandleDirtyOption();
                Interlocked.Exchange(ref _reentrancyFlag, 0);
            }
        }
Beispiel #17
0
 public void LogDebug(string data)
 {
     lock (_lock) LogWithRetries(() => Monitor.Debug($"NuGet: {data}"));
 }