private static BundlesInfo ParseNoneSharedBundleInfo(ref DependenciesInfo depsInfo, ref BundlesInfo sharedBundles)
        {
            // Parse none shared bundle info
            var noneSharedBundles = new BundlesInfo();

            foreach (var kv in depsInfo)
            {
                var assetName = kv.Key;
                var bundles   = kv.Value.referenceInBundles;

                var sharedBundle = sharedBundles.FirstOrDefault(skv => skv.Value.assets.Contains(assetName)).Key ?? "";

                foreach (var bundle in bundles)
                {
                    if (!string.IsNullOrEmpty(sharedBundles.FirstOrDefault(skv => skv.Key == bundle).Key))
                    {
                        continue; // Equals to shared bundle, pass.
                    }
                    if (!noneSharedBundles.ContainsKey(bundle))
                    {
                        noneSharedBundles.Add(bundle, new BundleInfo());
                    }

                    if (string.IsNullOrEmpty(sharedBundle))
                    {
                        noneSharedBundles[bundle].assets.Add(assetName);
                    }
                }
            }

            // Move *.unity files to independent bundles, because 'Cannot mark assets and scenes in one AssetBundle'
            var sceneBundles = new BundlesInfo();

            foreach (var kv in noneSharedBundles)
            {
                var noneSharedAssets = kv.Value.assets;
                var removed          = new List <string>();
                foreach (var asset in noneSharedAssets)
                {
                    if (!asset.EndsWith(".unity"))
                    {
                        continue;
                    }

                    var sceneBundleName = string.Format(BundlerBuildSettings.kSceneBundleFormatter,
                                                        PathUtility.RelativeProjectPathToAbsolutePath(asset));
                    sceneBundleName = PathUtility.NormalizeAssetBundlePath(sceneBundleName);

                    if (sceneBundles.ContainsKey(sceneBundleName))
                    {
                        throw new BundleException("Scene asset bundle duplicated: " + sceneBundleName);
                    }

                    var bundle = new BundleInfo();
                    bundle.assets.Add(asset);

                    sceneBundles.Add(sceneBundleName, bundle);

                    removed.Add(asset);
                }

                removed.ForEach(v => noneSharedAssets.Remove(v));
            }

            // Merge to none shared bundles
            foreach (var kv in sceneBundles)
            {
                noneSharedBundles.Add(kv.Key, kv.Value);
            }

            return(noneSharedBundles);
        }
        private static BundlesInfo ParseSharedBundleInfo(ref DependenciesInfo depsInfo,
                                                         ref ReservedSharedBundleInfo reserved, ref DependencyCache cache)
        {
            var sharedDict = new Dictionary <string, string>();

            var index = 0;

            // Determine shared bundles
            foreach (var kv in depsInfo)
            {
                var asset = kv.Key;

                // Ignore this asset when forced build in shared bundle.
                if (reserved.ContainsKey(asset))
                {
                    continue;
                }

                var depSet = kv.Value;

                // The count of dependencies no greater than 1 means that there are no other bundles
                // sharing this asset
                if (depSet.referenceInBundles.Count <= 1)
                {
                    continue;
                }

                // Otherwise, assets which depended by the same bundles will be separated to shared bundle.
                if (!sharedDict.ContainsKey(asset))
                {
                    sharedDict[asset] = string.Format(BundlerBuildSettings.kSharedBundleFormatter,
                                                      (++index).ToString());

                    // Sub-assets dependencies.
                    var deps = CollectDependencies(asset, ref cache);
                    foreach (var dep in deps)
                    {
                        if (reserved.ContainsKey(dep))
                        {
                            continue;
                        }
                        sharedDict[dep] = string.Format(BundlerBuildSettings.kSharedBundleFormatter,
                                                        (++index).ToString());
                    }
                }
            }

            // Collect shared bundles info
            var bundlesInfo = new BundlesInfo();

            foreach (var kv in sharedDict)
            {
                var name = sharedDict[kv.Key];
                if (bundlesInfo.ContainsKey(name))
                {
                    throw new BundleException("Shared bundle duplicated: " + name);
                }

                bundlesInfo[name] = new BundleInfo();
                bundlesInfo[name].assets.Add(kv.Key);
            }

            // Generate unique bundle name according to assets list.
            var sharedBundle = new BundlesInfo();

            foreach (var kv in bundlesInfo)
            {
                var assets = kv.Value.assets.ToList();
                assets.Sort((a, b) => string.Compare(a, b, StringComparison.Ordinal));

                var bundleName = string.Join("-", assets.ToArray());
                if (BundlerBuildSettings.kHashSharedBundle)
                {
                    using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(bundleName)))
                    {
                        var nameHash = CalculateMd5(stream);
                        bundleName = string.Format(BundlerBuildSettings.kSharedBundleFormatter, nameHash);
                    }
                }
                else
                {
                    bundleName = string.Format(BundlerBuildSettings.kSharedBundleFormatter, bundleName.ToLower());
                }

                var bundleInfo = new BundleInfo();
                foreach (var asset in kv.Value.assets)
                {
                    bundleInfo.assets.Add(asset);
                }
                sharedBundle.Add(bundleName, bundleInfo);
            }

            // Add reserved shared bundles info
            foreach (var kv in reserved)
            {
                var assetName = kv.Key;
                var bundle    = kv.Value;
                if (!sharedBundle.ContainsKey(bundle))
                {
                    sharedBundle.Add(bundle, new BundleInfo());
                }
                sharedBundle[bundle].assets.Add(assetName);
            }

            return(sharedBundle);
        }