private ApplicationDefinition CreateApplicationDefinition( List<Reference> references, IEnumerable<PackageFile> files ) { var defaultEnvironments = DefaultEnvironments.Select( e => ( TargetEnvironment )Enum.Parse( typeof( TargetEnvironment ), e ) ); var scripts = files.Where( f => f.Environment != TargetEnvironment.None ); var specifiedEnvironments = scripts.Where( f => f.Environment != TargetEnvironment.All ).Select( f => f.Environment ).Distinct(); specifiedEnvironments = specifiedEnvironments.Union( defaultEnvironments ); Guid = Guid.Replace( "{", "" ).Replace( "}", "" ); ApplicationDefinition appdef = new ApplicationDefinition { Name = Name, Guid = Guid }; // Create the module elements. foreach( var env in specifiedEnvironments ) { var module = new ApplicationModule { Environment = env.ToString().ToLower() }; appdef.Modules.Add( module ); // Add the bootstrap scripts. module.Files.Add( new ApplicationFile { Name = "_package_start.js" } ); // Add javascript files from the references. foreach( var r in references ) { var referencedScripts = r.GetScriptsForEnvironment( env ); foreach( var script in referencedScripts ) { var file = new ApplicationFile { Name = r.PackageName + "/" + script }; module.Files.Add( file ); } } // Add the application's own javascript files. var environmentScripts = scripts.Where( s => s.Environment == TargetEnvironment.All || s.Environment == env ); foreach( var script in environmentScripts ) { var file = new ApplicationFile { Name = script.PathInProject }; module.Files.Add( file ); } module.Files.Add( new ApplicationFile { Name = "_package_end.js" } ); } foreach( var db in files.Where(f => f.IsDashboard ) ) { var dashboard = new ApplicationDashboard { Id = Path.GetFileNameWithoutExtension(db.PathInProject), Content = db.PathInProject }; appdef.Dashboards.Add(dashboard); } foreach( var r in references ) { foreach( var db in r.GetDashboards() ) { var dashboard = new ApplicationDashboard { Id = db.Key, Content = r.PackageName + "/" + db.Value }; appdef.Dashboards.Add( dashboard ); } } return appdef; }
public override bool Execute() { Log.LogMessage( MessageImportance.Low, "Packing M-Files Application." ); // Gather all the JavaScript files var scripts = new List<string>(); scripts.AddRange( SourceFiles ); // Gather all reference files. // For now we do not support project or zip references so this step doesn't require anything special. var referenceFiles = References ?? new string[] { }; Log.LogMessage( MessageImportance.Low, "Resolving references." ); // Make sure the referenced files exist. var missingFiles = referenceFiles.Where( r => !File.Exists( r ) ).ToList(); foreach( var missingFile in missingFiles ) Log.LogError( "Referenced file '{0}' does not exist.", missingFile ); if( missingFiles.Count > 0 ) return false; // Resolve references by filename. var referencesByName = referenceFiles.GroupBy( f => Path.GetFileName( f ) ); // Resolve the final filenames. var finalReferences = new Dictionary<string, string>(); foreach( var nameGroup in referencesByName ) { var fileName = nameGroup.Key; var files = nameGroup.ToList(); if( fileName.ToLower() == "appdef.xml" ) continue; if( fileName.ToLower() == "_package.js" ) continue; for( int i = 0; i < files.Count; i++ ) { // If there are more than one file with the same name, use a $i as postfix for it. string postfix = ""; if( files.Count > 1 ) postfix = "$" + i; string finalFileName = Path.GetFileNameWithoutExtension( fileName ) + postfix + Path.GetExtension( fileName ); finalReferences[ files[ i ] ] = finalFileName; } } // Generate the package definition. var appdef = new ApplicationDefinition(); appdef.Guid = this.Guid.Replace("{", "").Replace("}", ""); appdef.Name = this.Name; var appfiles = new List<ApplicationFile>(); appfiles.Add( new ApplicationFile { Name = "_package.js" } ); foreach( var environment in new[] { "vaultcore", "vaultui", "shellui" } ) { var module = new ApplicationModule { Environment = environment }; appdef.Modules.Add( module ); module.Files = appfiles; } // Build the zip file. // Add the local scripts. if( File.Exists( OutputFile ) ) File.Delete( OutputFile ); var outputZip = new Ionic.Zip.ZipFile( OutputFile ); foreach( var file in SourceFiles ) { outputZip.AddFile( file ); appfiles.Add( new ApplicationFile { Name = file } ); } // Add the referenced scripts. foreach( var reference in finalReferences ) { var file = reference.Key; if( Path.GetExtension( file ) == ".zip" ) { var inputZip = new Ionic.Zip.ZipFile( file ); foreach( var e in inputZip.Entries ) { var filename = Path.GetFileName( e.FileName ).ToLower(); if( filename == "appdef.xml" ) continue; if( filename == "_package.js" ) continue; var tempStream = new MemoryStream(); e.Extract( tempStream ); tempStream.Position = 0; var projectName = Path.GetFileNameWithoutExtension( reference.Value ); var entryPath = "_references/" + projectName + "/" + e.FileName; outputZip.AddEntry( entryPath, tempStream ); appfiles.Add( new ApplicationFile { Name = entryPath } ); } } else { var entry = outputZip.AddFile( file ); entry.FileName = "_references/" + reference.Value; appfiles.Add( new ApplicationFile { Name = entry.FileName } ); } } var stream = new MemoryStream(); var serializer = new XmlSerializer( typeof( ApplicationDefinition ) ); serializer.Serialize( stream, appdef ); stream.Flush(); stream.Position = 0; outputZip.AddEntry( "appdef.xml", stream ); var packageStream = this.GetType().Assembly.GetManifestResourceStream( "MFiles.SDK.Tasks.Scripts.package.js" ); outputZip.AddEntry( "_package.js", packageStream ); outputZip.Save(); LogArray( "Scripts", outputZip.Entries.Select( e => e.FileName ) ); return true; }