private static void ParseBundleDependenciesByRuleOfPackBySubDirectory(BundleRule rule, ref DependenciesInfo depsInfo,
                                                                              ref ReservedSharedBundleInfo reserved, ref DependencyCache cache)
        {
            var excludePattern = rule.excludePattern;

            var searchPath     = PathUtility.RelativeProjectPathToAbsolutePath(rule.path);
            var subDirectories = Directory.GetDirectories(searchPath, "*.*", (SearchOption)rule.depth)
                                 .Where(v => !IsExclude(v, excludePattern))
                                 .ToArray();

            foreach (var subDirectory in subDirectories)
            {
                var files = Directory
                            .GetFiles(subDirectory, rule.searchPattern, SearchOption.AllDirectories)
                            .Where(v => !IsMeta(v))
                            .Where(v => !IsExclude(v, excludePattern))
                            .ToArray();

                var bundleName = PathUtility.NormalizeAssetBundlePath(subDirectory);
                bundleName = string.Format(BundlerBuildSettings.kBundleFormatter, bundleName);
                bundleName = BundlerBuildSettings.kHashAssetBundlePath
                    ? PathUtility.HashPath(bundleName)
                    : bundleName;

                try {
                    var index = 0;
                    foreach (var file in files)
                    {
                        EditorUtility.DisplayProgressBar("Parsing Rule of Pack By Sub Directory Name", file,
                                                         (float)index++ / files.Length);

                        var relativePath = PathUtility.AbsolutePathToRelativeProjectPath(file);
                        if (rule.shared)
                        {
                            TryAddToForceSharedBundle(relativePath, bundleName, ref reserved);
                        }

                        AddDependenciesInfo(bundleName, relativePath, ref depsInfo, ref reserved, ref cache);
                    }
                }
                finally {
                    EditorUtility.ClearProgressBar();
                }
            }
        }
        private static void RegenerateAssetBundle(string path, BuildTarget platform)
        {
            var bundleOutputFullPath =
                PathUtility.Combine(Application.streamingAssetsPath, BundlerBuildSettings.kBundlePath);
            var bundleOutputRelativePath = PathUtility.AbsolutePathToRelativeProjectPath(bundleOutputFullPath);
            var manifestFilePath         = PathUtility.Combine(bundleOutputFullPath, BundlerBuildSettings.kManifestFileName);

            var bundleName = path.Substring(bundleOutputRelativePath.Length + 1);
            var jsonText   = File.ReadAllText(manifestFilePath);
            var manifest   = JsonUtility.FromJson <BundlerManifest>(jsonText);

            if (!manifest.bundles.ContainsKey(bundleName))
            {
                Debug.LogErrorFormat("Cannot found asset bundle in manifest: {0}", bundleName);
                return;
            }

            BundlerGenerator.RegenerateAssetBundle(manifest, bundleName, platform, bundleOutputRelativePath);
        }
        public static void GenerateManifest()
        {
            var stopWatch = new Stopwatch();

            stopWatch.Start();

            var buildRuleFile         = PathUtility.RelativeDataPathToAbsolutePath(BundlerBuildSettings.kBuildRuleFilePath);
            var relativeBuildRuleFile = PathUtility.AbsolutePathToRelativeProjectPath(buildRuleFile);
            var buildRuleAsset        = AssetDatabase.LoadAssetAtPath <TextAsset>(relativeBuildRuleFile);
            var buildRule             = JsonUtility.FromJson <BundlerBuildRule>(buildRuleAsset.text);

            var outputPath =
                PathUtility.Combine(BundlerBuildSettings.kBundlePath, BundlerBuildSettings.kManifestFileName);
            var fullPath = PathUtility.Combine(Application.streamingAssetsPath, outputPath);

            BundlerGenerator.GenerateManifestToFile(buildRule, fullPath);

            stopWatch.Stop();
            Debug.Log(string.Format("Generate manifest finished, cost: {0}s", stopWatch.Elapsed.TotalSeconds));
        }
        public static void StripUnmanagedFiles()
        {
            var buildRuleFile         = PathUtility.RelativeDataPathToAbsolutePath(BundlerBuildSettings.kBuildRuleFilePath);
            var relativeBuildRuleFile = PathUtility.AbsolutePathToRelativeProjectPath(buildRuleFile);
            var buildRuleAsset        = AssetDatabase.LoadAssetAtPath <TextAsset>(relativeBuildRuleFile);
            var buildRule             = JsonUtility.FromJson <BundlerBuildRule>(buildRuleAsset.text);

            var manifestFile =
                PathUtility.Combine(BundlerBuildSettings.kBundlePath, BundlerBuildSettings.kManifestFileName);
            var manifestFileFullPath = PathUtility.Combine(Application.streamingAssetsPath, manifestFile);

            if (!File.Exists(manifestFileFullPath))
            {
                EditorUtility.DisplayDialog("Error", "Please generate bundler manifest first.", "OK");
                return;
            }

            var manifestText = File.ReadAllText(manifestFileFullPath);
            var manifest     = JsonUtility.FromJson <BundlerManifest>(manifestText);

            BundlerGenerator.StripUnmanagedFiles(buildRule, manifest);
            manifestText = JsonUtility.ToJson(manifest);
            File.WriteAllText(manifestFileFullPath, manifestText);
        }
        /// <summary>
        /// Validate bundle dependencies
        /// </summary>
        /// <param name="manifest"></param>
        /// <param name="outputPath"></param>
        /// <exception cref="BundleException"></exception>
        public static void ValidateBundleDependencies(BundlerManifest manifest, string outputPath)
        {
            var abManifestPath         = string.Format("{0}/{1}", outputPath, new DirectoryInfo(outputPath).Name);
            var abManifestRelativePath = PathUtility.AbsolutePathToRelativeProjectPath(abManifestPath);
            var ab = AssetBundle.LoadFromFile(abManifestRelativePath);

            if (!ab)
            {
                throw new BundleException("Load asset bundle failed: " + abManifestPath);
            }

            var abManifest = ab.LoadAsset <AssetBundleManifest>("AssetBundleManifest");

            if (!abManifest)
            {
                ab.Unload(true);
                throw new BundleException("Load asset bundle manifest failed: " + abManifestPath);
            }

            void ValidateBundle(string assetBundle, List <string> validated)
            {
                if (validated.Contains(assetBundle))
                {
                    throw new BundleException("Circular dependency detected: " + assetBundle);
                }
                validated.Add(assetBundle);

                if (!manifest.bundles.ContainsKey(assetBundle))
                {
                    throw new BundleException("Bundle does not contain in manifest: " + assetBundle);
                }

                var dependencies = abManifest.GetDirectDependencies(assetBundle);

                foreach (var dependency in dependencies)
                {
                    if (!manifest.bundles[assetBundle].dependencies.Contains(dependency))
                    {
                        throw new BundleException(string.Format(
                                                      "Bundle dependencies lost, bundle name: {0}, dependency: {1}", assetBundle, dependency));
                    }
                    //Debug.Log("Validating dependency: " + dependency);
                    ValidateBundle(dependency, validated);
                }
                validated.Remove(assetBundle);
            }

            var index = 0f;
            var abs   = abManifest.GetAllAssetBundles();

            try {
                foreach (var assetBundle in abs)
                {
                    EditorUtility.DisplayProgressBar("Validating asset bundle", assetBundle, index++ / abs.Length);
                    //Debug.Log("Validating asset bundle: " + assetBundle);
                    ValidateBundle(assetBundle, new List <string>());
                }
            }
            finally {
                EditorUtility.ClearProgressBar();
                ab.Unload(true);
                AssetBundle.UnloadAllAssetBundles(true);
            }
        }