Example #1
0
        internal static RemoteAssemblyState ParseFromManifestRow(RemoteAssemblyManifest manifest, string line)
        {
            string[] columns = line.Split(',');
            if (columns.Length < 11)
            {
                return(null);
            }
            string id                        = columns[0].Trim();
            string url                       = columns[1].Trim();
            string directoryName             = columns[2].Trim();
            string isStable                  = columns[3].Trim();
            string wasExplicitVersionRequest = columns[4].Trim();
            string lastUsedTimestampRaw      = columns[5].Trim();
            string lastLatestCheckRaw        = columns[6].Trim();
            string hasCni                    = columns[7].Trim();
            string isDllDownloaded           = columns[8].Trim();

            string[] platformsRaw         = columns[9].Split('|').Select(s => s.Trim()).Where(s => s.Length > 0).ToArray();
            string[] platforms            = platformsRaw.Select(s => s[0] == '*' ? s.Substring(1) : s).ToArray();
            bool[]   platformIsDownloaded = platformsRaw.Select(s => s[0] == '*').ToArray();

            string version = columns[10];

            for (int i = 11; i < columns.Length; ++i)
            {
                version += "," + columns[i];
            }
            version = version.Trim();

            int lastUsedTimestamp;
            int lastLatestCheck;

            if (!int.TryParse(lastUsedTimestampRaw, out lastUsedTimestamp) ||
                !int.TryParse(lastLatestCheckRaw, out lastLatestCheck))
            {
                return(null);
            }

            RemoteAssemblyState ras = new RemoteAssemblyState(manifest)
            {
                Id                  = id,
                LastUsed            = lastUsedTimestamp,
                LastLatestCheck     = lastLatestCheck,
                LocalDirectory      = directoryName,
                Url                 = url,
                Version             = version,
                IsLatestStable      = wasExplicitVersionRequest == "1",
                IsStable            = isStable == "1",
                HasCni              = hasCni == "1",
                RuntimeIsDownloaded = isDllDownloaded == "1",
            };

            for (int i = 0; i < platforms.Length; ++i)
            {
                ras.platformsSupportedAndCurrentSyncState[platforms[i]] = platformIsDownloaded[i];
            }

            return(ras);
        }
Example #2
0
        private IList <RemoteAssemblyState> Parse()
        {
            string manifestFile = this.ManifestFilePath;

            if (!File.Exists(manifestFile))
            {
                return(new RemoteAssemblyState[0]);
            }

            int now = CommonUtil.DateTime.Time.UnixTimeNow;

            List <RemoteAssemblyState> remoteAssemblies = new List <RemoteAssemblyState>();
            List <string> invalidLines = new List <string>();

            foreach (string line in File.ReadLines(manifestFile))
            {
                string trimmedLine = line.Trim();
                if (trimmedLine.Length > 0)
                {
                    RemoteAssemblyState state = RemoteAssemblyState.ParseFromManifestRow(this, trimmedLine);
                    if (state == null)
                    {
                        invalidLines.Add(line);
                    }
                    else
                    {
                        string outermostPath = Path.Join(this.Directory, state.LocalDirectory);
                        if (FileUtil.DirectoryExists(outermostPath))
                        {
                            if (FileUtil.FileExists(Path.Join(state.AbsolutePathToLibrary, "manifest.json")) &&
                                now - state.LastUsed < DELETE_ASSEMBLIES_THAT_HAVENT_BEEN_USED_IN_THIS_MANY_DAYS * 24 * 3600)
                            {
                                remoteAssemblies.Add(state);
                            }
                            else
                            {
                                FileUtil.DirectoryDelete(outermostPath);
                            }
                        }
                    }
                }
            }

            foreach (string line in invalidLines)
            {
                Common.ConsoleWriter.Print(ConsoleMessageType.REMOTE_ASSEMBLY_ERROR, "Invalid assembly in manifest! Ignoring: " + line);
            }

            return(remoteAssemblies);
        }
Example #3
0
        internal void AddOrReplaceAssemblyState(RemoteAssemblyState assembly)
        {
            bool alreadyExists = false;

            foreach (RemoteAssemblyState existingAssembly in this.remoteAssemblies.Where(a => a.Url == assembly.Url))
            {
                if (existingAssembly.Version == assembly.Version)
                {
                    alreadyExists = true;
                    existingAssembly.IsLatestStable = assembly.IsLatestStable;
                    existingAssembly.IsStable       = assembly.IsStable;
                }
                else if (assembly.IsLatestStable)
                {
                    existingAssembly.IsLatestStable = false;
                }
            }

            if (!alreadyExists)
            {
                this.remoteAssemblies.Add(assembly);
            }
        }
Example #4
0
        public Pair <FetchAssemblyStatus, RemoteAssemblyState> FetchNewAssembly(RemoteAssemblyManifest manifest, string urlAndVersion)
        {
            RemoteAssemblyUrl structuredUrl = RemoteAssemblyUrl.FromUrl(urlAndVersion);

            if (!structuredUrl.IsValid)
            {
                return(new Pair <FetchAssemblyStatus, RemoteAssemblyState>(FetchAssemblyStatus.INVALID_URL, null));
            }

            HttpRequest requestSender = new HttpRequest("GET", structuredUrl.Url)
                                        .SetHeader("CrayonLib-Component-Type", "source")
                                        .SetHeader("User-Agent", Common.VersionInfo.UserAgent);

            if (!structuredUrl.IsLatestStableVersionRequested)
            {
                requestSender.SetHeader("CrayonLib-Version-Info", structuredUrl.VersionInfo);
            }

            HttpResponse response = requestSender.Send();
            Pair <FetchAssemblyStatus, RemoteAssemblyState> error = CheckForBasicErrors(response, structuredUrl.LibraryName);

            if (error != null)
            {
                return(error);
            }

            string versionInfo = response.GetHeader("CrayonLib-Version-Info");
            // Not used. Not sure why this is returned.
            // string componentType = response.GetHeader("CrayonLib-Component-Type");
            bool hasNativeInterface = response.GetHeaderAsBoolean("CrayonLib-Has-Native-Interface");

            string[] platformsSupported = response.GetHeaderAsList("CrayonLib-Platforms-Supported");
            string   libraryName        = response.GetHeader("CrayonLib-Library-Name");
            bool     isStable           = response.GetHeaderAsBoolean(("CrayonLib-Is-Stable"));
            string   directoryName      = this.CreateNewDirectoryForLibrary(manifest.Directory, libraryName, versionInfo);

            byte[]        crypkg        = response.Content;
            CryPkgDecoder crypkgDecoder = new CryPkgDecoder(response.Content);

            // TODO: crypkgDecoder.IsValid

            this.ExpandCryPkgToDirectory(crypkgDecoder, Path.Join(manifest.Directory, directoryName, libraryName));
            int now = CommonUtil.DateTime.Time.UnixTimeNow;
            RemoteAssemblyState ras = new RemoteAssemblyState(manifest)
            {
                HasCni              = hasNativeInterface,
                Id                  = libraryName,
                IsStable            = isStable,
                IsLatestStable      = structuredUrl.IsLatestStableVersionRequested,
                LastUsed            = now,
                LastLatestCheck     = now,
                LocalDirectory      = directoryName,
                RuntimeIsDownloaded = false,
                Url                 = structuredUrl.Url,
                Version             = versionInfo,
            };

            foreach (string platformSupported in platformsSupported)
            {
                ras.IndicatePlatformSupport(platformSupported);
            }

            return(new Pair <FetchAssemblyStatus, RemoteAssemblyState>(FetchAssemblyStatus.SUCCESS, ras));
        }
Example #5
0
        public IList<AssemblyMetadata> GetRemoteAssemblies(string[] urlsAndVersionInfo)
        {
            Dictionary<string, AssemblyMetadata> assemblies = new Dictionary<string, AssemblyMetadata>();
            if (urlsAndVersionInfo == null || urlsAndVersionInfo.Length == 0) return new AssemblyMetadata[0];

            RemoteAssemblyManifest manifest = new RemoteAssemblyManifest();
            List<string[]> librariesMissing = new List<string[]>();
            List<RemoteAssemblyState> librariesThatMightNeedRefresh = new List<RemoteAssemblyState>();
            bool anyLibrariesWereMissing = false;
            List<RemoteAssemblyState> usedAssemblies = new List<RemoteAssemblyState>();
            foreach (string info in urlsAndVersionInfo)
            {
                string[] parts = StringUtil.SplitOnce(info, ",");
                string url = parts[0];
                string version = null;
                if (parts.Length == 2)
                {
                    version = parts[1] == "LATEST" ? null : parts[1];
                }
                bool isLatestStableRequested = version == null;

                RemoteAssemblyState currentState = manifest.GetAssemblyState(url, version);
                if (currentState == null)
                {
                    currentState = PerformSyncForMissingAssembly(manifest, url, version);
                    if (currentState == null) throw new System.Exception(); // all code paths that return null from the above function should have thrown a proper error message exception.
                    anyLibrariesWereMissing = true;
                    usedAssemblies.Add(currentState);
                }
                else if (isLatestStableRequested)
                {
                    librariesThatMightNeedRefresh.Add(currentState);
                }
                else
                {
                    usedAssemblies.Add(currentState);
                }
            }

            int now = CommonUtil.DateTime.Time.UnixTimeNow;
            int ageToDefinitelySync = 7 * 24 * 3600;
            int expiration = now - ageToDefinitelySync;
            bool refreshNeeded = anyLibrariesWereMissing || librariesThatMightNeedRefresh.Where(lib => lib.LastLatestCheck < expiration).FirstOrDefault() != null;
            if (refreshNeeded)
            {
                foreach (RemoteAssemblyState lib in librariesThatMightNeedRefresh)
                {
                    RemoteAssemblyState nullableNewLib = PerformSyncForOptionalRefresh(manifest, lib.Url);
                    usedAssemblies.Add(nullableNewLib ?? lib);
                }
            }
            else
            {
                usedAssemblies.AddRange(librariesThatMightNeedRefresh);
            }

            foreach (RemoteAssemblyState ras in usedAssemblies)
            {
                ras.LastUsed = now;
            }

            manifest.ReserializeFile();

            foreach (RemoteAssemblyState ras in usedAssemblies)
            {
                assemblies.Add(ras.Id, new AssemblyMetadata(ras.AbsolutePathToLibrary, ras.Id));
            }

            return assemblies.Values.ToArray();
        }