コード例 #1
0
        public override void Execute(AppOptionInfo opts, CodeGenRunner codeGenRunner)
        {
            Console.WriteLine("\n\nGenerating for all entities...");

            var codeMapFile = GetCodeMapFile(opts);

            var template = Path.Combine(codeGenRunner.TemplateFolder, opts.TemplateName);

            if (!File.Exists(template))
            {
                throw new GoliathDataException(string.Format("template file {0} not found.", template));
            }

            var map = MapConfig.Create(codeMapFile, true);

            map.Settings.AssemblyName         = opts.AssemblyName;
            map.Settings.Namespace            = opts.Namespace;
            map.Settings.AdditionalNamespaces = codeGenRunner.Settings.AdditionalNamespaces;
            map.Settings.GenerateLinkTable    = codeGenRunner.Settings.GenerateLinkTable;

            if (!Directory.Exists(codeGenRunner.WorkingFolder))
            {
                Directory.CreateDirectory(codeGenRunner.WorkingFolder);
            }

            codeGenRunner.GenerateClassesFromTemplate(map, template, codeGenRunner.WorkingFolder,
                                                      (name, iteration) => GetFileName(name, iteration, opts.OutputFile), opts.ExtendedProperties, opts.ExcludedArray);
        }
コード例 #2
0
        public override void Execute(AppOptionInfo opts, CodeGenRunner codeGenRunner)
        {
            Console.WriteLine("\n\nGenerating Entities...");

            var codeMapFile = GetCodeMapFile(opts);

            var template = Path.Combine(codeGenRunner.TemplateFolder, "TrackableClass.razt");

            if (!File.Exists(template))
            {
                throw new GoliathDataException($"template file {template} not found.");
            }

            if (!Directory.Exists(codeGenRunner.WorkingFolder))
            {
                Directory.CreateDirectory(codeGenRunner.WorkingFolder);
            }

            var map = MapConfig.Create(codeMapFile, true);

            map.Settings.AssemblyName         = opts.AssemblyName;
            map.Settings.Namespace            = opts.Namespace;
            map.Settings.AdditionalNamespaces = codeGenRunner.Settings.AdditionalNamespaces;
            map.Settings.GenerateLinkTable    = codeGenRunner.Settings.GenerateLinkTable;

            codeGenRunner.GenerateClasses(map, opts.ExtendedProperties, opts.ExcludedArray);
        }
コード例 #3
0
        void ExportToSql(ExportModel data, AppOptionInfo opts, EntityMap entityMap, CodeGenRunner codeGenRunner, string template, List <string> files)
        {
            var fileName = GetFileName(entityMap.Name, entityMap.SortOrder, opts.OutputFile);

            codeGenRunner.GenerateCodeFromTemplate(data, template, codeGenRunner.WorkingFolder, fileName);
            files.Add(Path.Combine(codeGenRunner.WorkingFolder, fileName));
        }
コード例 #4
0
 public void ShouldThrowExceptionOnConsolidateTemplates(string[] templatesPaths, TemplateDuplicationHandlingStrategy templateDuplicationHandlingStrategy, string expectedMessage)
 {
     Should.Throw <InvalidDataException>(() =>
     {
         CodeGenRunner.GetTemplates(templatesPaths.ToList(), templateDuplicationHandlingStrategy).ToList();
     }
                                         ).Message.ShouldBe(expectedMessage);
 }
コード例 #5
0
        public void ShouldKeepOnConsolidateTemplates(string[] templatesPaths, string expectedTemplateFolder, TemplateDuplicationHandlingStrategy templateDuplicationHandlingStrategy, int expectedTemplatesCount)
        {
            var templates = CodeGenRunner.GetTemplates(templatesPaths.ToList(), templateDuplicationHandlingStrategy).ToList();

            templates.Count.ShouldBe(expectedTemplatesCount);

            foreach (var template in templates)
            {
                Assert.Contains(expectedTemplateFolder, template.FilePath);
            }
        }
コード例 #6
0
        public void ShouldNotThrowExceptionOnConsolidateTemplates(string[] templatesPaths, TemplateDuplicationHandlingStrategy templateDuplicationHandlingStrategy)
        {
            var templates = CodeGenRunner.GetTemplates(templatesPaths.ToList(), templateDuplicationHandlingStrategy).ToList();

            Assert.Equal(5, templates.Count);

            Assert.Contains(templates, template => template.FileName == "path1");
            Assert.Contains(templates, template => template.FileName == "path2");
            Assert.Contains(templates, template => template.FileName == "path3");
            Assert.Contains(templates, template => template.FileName == "path4");
        }
コード例 #7
0
        void ExportToXml(ExportModel data, AppOptionInfo opts, EntityMap entityMap, CodeGenRunner codeGenRunner, List <string> files)
        {
            var fileName     = GetFileName(entityMap.Name, null, opts.OutputFile);
            var exportedData = new ExportedDataModel
            {
                EntityName = entityMap.FullName,
                Name       = entityMap.TableName,
                DataRows   = data.DataBag
            };

            var filePath = Path.Combine(codeGenRunner.WorkingFolder, fileName);

            exportedData.Save(filePath);
            files.Add(filePath);
        }
コード例 #8
0
        public override void Execute(AppOptionInfo opts, CodeGenRunner codeGenRunner)
        {
            var codeMapFile = GetCodeMapFile(opts);
            var map         = MapConfig.Create(codeMapFile, true);

            map.Settings.AssemblyName         = opts.AssemblyName;
            map.Settings.Namespace            = opts.Namespace;
            map.Settings.AdditionalNamespaces = codeGenRunner.Settings.AdditionalNamespaces;
            map.Settings.GenerateLinkTable    = codeGenRunner.Settings.GenerateLinkTable;

            if (string.IsNullOrWhiteSpace(opts.TemplateName))
            {
                throw new GoliathDataException("Template file to use is required for generate operation. Please make sure that -in=\"Template_File_name.razt\" argument is passed in.");
            }

            var template = Path.Combine(codeGenRunner.TemplateFolder, opts.TemplateName);

            if (!File.Exists(template))
            {
                throw new GoliathDataException($"template file {template} not found.");
            }

            if (string.IsNullOrWhiteSpace(opts.OutputFile))
            {
                throw new GoliathDataException("Output file is required for generate operation. Please make sure that -out=\"YOUR_FILE.EXT\" argument is passed in.");
            }

            if (!Directory.Exists(codeGenRunner.WorkingFolder))
            {
                Directory.CreateDirectory(codeGenRunner.WorkingFolder);
            }

            if (!string.IsNullOrWhiteSpace(opts.EntityModel))
            {
                Logger.Log(LogLevel.Debug, $"Extracting model {opts.EntityModel} from map entity models.");

                if (map.EntityConfigs.TryGetValue(opts.EntityModel, out var entMap))
                {
                    codeGenRunner.GenerateCodeFromTemplate(entMap, template, codeGenRunner.WorkingFolder, opts.OutputFile);
                }
            }
            else
            {
                codeGenRunner.GenerateCodeFromTemplate(map, template, codeGenRunner.WorkingFolder, opts.OutputFile, opts.ExtendedProperties);
            }
        }
コード例 #9
0
        public override void Execute(AppOptionInfo opts, CodeGenRunner codeGenRunner)
        {
            var codeMapFile = GetCodeMapFile(opts);
            var mainMap     = MapConfig.Create(codeMapFile, true);

            string mapfile2 = opts.TemplateName;

            if (!File.Exists(mapfile2))
            {
                throw new GoliathDataException(string.Format("map file {0} does not exist", mapfile2));
            }

            var secondMap = MapConfig.Create(mapfile2, true);

            mainMap.MergeMap(secondMap);
            CodeGenRunner.ProcessMappedStatements(mainMap);
            mainMap.Save(codeMapFile, true);
        }
コード例 #10
0
        public async Task ShouldGetAndApplyOpenApiTemplates(SourceSchemaType schemaType, string schemaPath, string[] templatesPaths, string expectedResultPath)
        {
            var tmpFolder = Path.GetRandomFileName();

            try
            {
                var loader = schemaType.GetSchemaLoader();

                await CodeGenRunner.RunAsync(new[] { schemaPath }, loader, templatesPaths.ToList(), tmpFolder, null);

                var expectedFiles = Directory.GetFiles(expectedResultPath, "*.*", SearchOption.AllDirectories).ToArray();
                var resultFiles   = Directory.GetFiles(tmpFolder, "*.*", SearchOption.AllDirectories).ToArray();

                resultFiles
                .Select(f => Path.GetRelativePath(tmpFolder, f)).OrderBy(f => f)
                .ShouldBe(expectedFiles.Select(f => Path.GetRelativePath(expectedResultPath, f)).OrderBy(f => f));

                foreach (var expectedFile in expectedFiles)
                {
                    var relativePath = Path.GetRelativePath(expectedResultPath, expectedFile);
                    var resultPath   = Path.Combine(tmpFolder, relativePath);

                    if (!File.Exists(resultPath))
                    {
                        throw new FileNotFoundException($"File {relativePath} should be output from the template runner.");
                    }

                    _output.WriteLine($"Testing {relativePath} content.");

                    File.ReadAllText(resultPath).Replace("\r\n", "\n")
                    .ShouldBe(File.ReadAllText(expectedFile).Replace("\r\n", "\n"));
                }
            }
            finally
            {
                if (Directory.Exists(tmpFolder))
                {
                    Directory.Delete(tmpFolder, true);
                }
            }
        }
コード例 #11
0
ファイル: ImportAction.cs プロジェクト: malweka/GoliathData
        public override void Execute(AppOptionInfo opts, CodeGenRunner codeGenRunner)
        {
            bool zipFile = false || !string.IsNullOrWhiteSpace(opts.TemplateName) && opts.TemplateName.ToUpper().EndsWith(".ZIP");

            var codeMapFile = GetCodeMapFile(opts);
            var map         = MapConfig.Create(codeMapFile, true);

            map.Settings.AssemblyName         = opts.AssemblyName;
            map.Settings.Namespace            = opts.Namespace;
            map.Settings.AdditionalNamespaces = codeGenRunner.Settings.AdditionalNamespaces;

            var importRdbms     = GetRdbms(opts.ImportSqlDialect);
            var providerFactory = new ProviderFactory();
            var dbConnector     = providerFactory.CreateDbConnector(importRdbms, opts.ConnectionString);

            //var dialect = providerFactory.CreateDialect(importRdbms);

            Logger.Log(LogLevel.Debug, $"Importing using {importRdbms}");

            if (!Directory.Exists(codeGenRunner.WorkingFolder))
            {
                Directory.CreateDirectory(codeGenRunner.WorkingFolder);
            }

            if (zipFile)
            {
                var inputFile = Path.Combine(opts.WorkingFolder, opts.TemplateName);
                if (!File.Exists(inputFile))
                {
                    throw new ArgumentException($"Could not find the input file: {inputFile}");
                }

                using (var fs = File.Open(inputFile, FileMode.Open, FileAccess.Read))
                {
                    fs.Unzip(opts.WorkingFolder);
                }
            }

            var files = Directory.EnumerateFiles(opts.WorkingFolder, "*.xml").ToDictionary(Path.GetFileNameWithoutExtension);

            using (var conn = dbConnector.CreateNewConnection() as SqlConnection)
            {
                if (conn == null)
                {
                    throw new InvalidOperationException("Import is only supported on SQL Server for now.");
                }

                conn.Open();
                var transaction = conn.BeginTransaction();

                try
                {
                    foreach (var table in map.EntityConfigs)
                    {
                        if (!files.TryGetValue(table.Name, out var file))
                        {
                            continue;
                        }

                        Logger.Log(LogLevel.Debug, $"Reading: {file}");
                        ImportData(map, conn, transaction, opts, file);
                    }

                    transaction.Commit();
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                    throw;
                }
                finally
                {
                    transaction.Dispose();
                }
            }
        }
コード例 #12
0
        public override void Execute(AppOptionInfo opts, CodeGenRunner codeGenRunner)
        {
            Console.WriteLine("\n\nCreate Map...");
            var         providerFactory = new ProviderFactory();
            ComplexType baseModel       = null;
            var         mapFileName     = Path.Combine(opts.WorkingFolder, opts.MapFile);
            var         baseMap         = new MapConfig();

            if (!string.IsNullOrWhiteSpace(opts.BaseModelXml) && File.Exists(opts.BaseModelXml))
            {
                Console.WriteLine("\n\nRead base model.");
                baseMap.Load(opts.BaseModelXml);
                if (baseMap.ComplexTypes.Count > 0)
                {
                    baseModel = baseMap.ComplexTypes[0];
                    codeGenRunner.Settings.BaseModel = baseModel.FullName;
                }
            }

            var rdbms = GetSupportedRdbms(opts);

            string[] whiteList;

            FilterSettings filterSettings = new FilterSettings();

            if (!string.IsNullOrWhiteSpace(opts.Include))
            {
                whiteList = opts.Include.Split(new string[] { ",", "|" }, StringSplitOptions.RemoveEmptyEntries);
                filterSettings.Exclude         = false;
                filterSettings.TableFilterList = whiteList;
            }
            else
            {
                filterSettings.Exclude         = true;
                filterSettings.TableFilterList = opts.ExcludedArray;
            }

            using (ISchemaDescriptor schemaDescriptor = providerFactory
                                                        .CreateDbSchemaDescriptor(rdbms, codeGenRunner.Settings, filterSettings))
            {
                var map = codeGenRunner.CreateMap(schemaDescriptor, opts.EntitiesToRename, baseModel, mapFileName);
                if (!string.IsNullOrWhiteSpace(opts.MappedStatementFile) && File.Exists(opts.MappedStatementFile))
                {
                    Console.WriteLine("Load mapped statements from {0} into {1}", opts.MappedStatementFile, mapFileName);
                    map.LoadMappedStatements(opts.MappedStatementFile);
                    CodeGenRunner.ProcessMappedStatements(map);
                }

                //let's try to read order from log if exists
                string primaOrda         = Path.Combine(opts.WorkingFolder, PrimaOrdaFile);
                var    previousOrderDict = new Dictionary <string, Tuple <int, string> >();
                var    orderCount        = 0;
                if (File.Exists(primaOrda))
                {
                    using (var sr = new StreamReader(primaOrda))
                    {
                        var contentLog = sr.ReadToEnd();
                        if (!string.IsNullOrWhiteSpace(contentLog))
                        {
                            var split = contentLog.Split(new string[] { "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries);
                            for (var i = 0; i < split.Length; i++)
                            {
                                var tbName = split[i];
                                previousOrderDict.Add(tbName, Tuple.Create(i + 1, tbName));
                            }

                            orderCount = split.Length;
                        }
                    }
                }

                map.MergeMap(baseMap);

                foreach (var ent in map.EntityConfigs)
                {
                    ProcessMetadata(opts, ent);
                    ProcessActivatedProperties(opts, ent);

                    Tuple <int, string> tbOrder;
                    if (previousOrderDict.TryGetValue(ent.FullName, out tbOrder))
                    {
                        ent.Order = tbOrder.Item1;
                    }
                    else
                    {
                        previousOrderDict.Add(ent.FullName, Tuple.Create(ent.Order, ent.FullName));
                        orderCount = orderCount + 1;
                        ent.Order  = orderCount;
                    }

                    //process keygen
                    if (!string.IsNullOrWhiteSpace(opts.DefaultKeygen))
                    {
                        if (ent.PrimaryKey != null)
                        {
                            foreach (var k in ent.PrimaryKey.Keys)
                            {
                                if (string.IsNullOrWhiteSpace(k.KeyGenerationStrategy))
                                {
                                    k.KeyGenerationStrategy = opts.DefaultKeygen;
                                }
                            }
                        }
                    }

                    foreach (var prop in ent)
                    {
                        ProcessMetadata(opts, ent, prop);
                        ProcessActivatedProperties(opts, ent, prop);

                        if (!string.IsNullOrWhiteSpace(opts.ComplexTypeMap))
                        {
                            var    key = string.Concat(ent.Name, ".", prop.Name);
                            string complextType;
                            if (opts.ComplexTypesTypeMap.TryGetValue(key, out complextType))
                            {
                                prop.ComplexTypeName = complextType;
                                prop.IsComplexType   = true;
                                opts.ComplexTypesTypeMap.Remove(key);
                            }
                        }
                    }

                    var unprocessedComplexTypes = opts.ComplexTypesTypeMap.Where(c => c.Key.StartsWith($"{ent.Name}.")).ToList();
                    if (unprocessedComplexTypes.Count > 0)
                    {
                        ProcessComplexTypes(unprocessedComplexTypes, ent, map);
                    }
                }

                map.Save(mapFileName, true, true);
                using (var file = new StreamWriter(primaOrda))
                {
                    foreach (var tbOrder in previousOrderDict.Keys)
                    {
                        file.WriteLine(tbOrder);
                    }
                }
            }
        }
コード例 #13
0
        public override void Execute(AppOptionInfo opts, CodeGenRunner codeGenRunner)
        {
            var codeMapFile = GetCodeMapFile(opts);
            var map         = MapConfig.Create(codeMapFile, true);

            map.Settings.AssemblyName         = opts.AssemblyName;
            map.Settings.Namespace            = opts.Namespace;
            map.Settings.AdditionalNamespaces = codeGenRunner.Settings.AdditionalNamespaces;
            map.Settings.GenerateLinkTable    = codeGenRunner.Settings.GenerateLinkTable;

            var providerFactory = new ProviderFactory();

            var importRdbms = GetRdbms(opts.ImportSqlDialect);
            var exportRdbms = GetRdbms(opts.ExportSqlDialect);

            var dbConnector = providerFactory.CreateDbConnector(importRdbms, opts.ConnectionString);

            if (string.IsNullOrWhiteSpace(opts.TemplateName))
            {
                throw new GoliathDataException("Template file to use is required for generate operation. Please make sure that -in=\"Template_File_name.razt\" argument is passed in.");
            }

            var template = Path.Combine(codeGenRunner.TemplateFolder, opts.TemplateName);

            if (!File.Exists(template))
            {
                throw new GoliathDataException($"template file {template} not found.");
            }

            if (string.IsNullOrWhiteSpace(opts.OutputFile))
            {
                throw new GoliathDataException("Output file is required for generate operation. Please make sure that -out=\"YOUR_FILE.EXT\" argument is passed in.");
            }

            if (string.IsNullOrWhiteSpace(opts.Include))
            {
                Logger.Log(LogLevel.Warning, "No table to read for enum provided. Please make sure you set the include parameter properly");
                return;
            }

            var tables = opts.Include.Split(new string[] { ",", ";", "|" }, StringSplitOptions.RemoveEmptyEntries);


            var exporter = new DataExporterAdapter(providerFactory.CreateDialect(importRdbms), providerFactory.CreateDialect(exportRdbms),
                                                   dbConnector, new TypeConverterStore());

            var counter = 0;

            List <string>      errors = new List <string>();
            List <ExportModel> models = new List <ExportModel>();

            foreach (var tbl in tables)
            {
                try
                {
                    Logger.Log(LogLevel.Info, $"Processing entity {tbl}");
                    var entityMap = map.GetEntityMap($"{opts.Namespace}.{tbl}");

                    counter++;
                    var data = exporter.Export(entityMap, opts.ExportIdentityColumn, opts.ExportDatabaseGeneratedColumns);
                    //var fileName = GetFileName(entityMap.Name, counter, opts.OutputFile);

                    if (data == null || data.DataBag.Count == 0)
                    {
                        Logger.Log(LogLevel.Warning, $"No data found for {tbl}");
                        continue;
                    }

                    models.Add(data);
                }
                catch (Exception ex)
                {
                    errors.Add($"Error entity [{tbl}]: {ex.ToString()}");
                }
            }

            if (!Directory.Exists(codeGenRunner.WorkingFolder))
            {
                Directory.CreateDirectory(codeGenRunner.WorkingFolder);
            }

            codeGenRunner.GenerateCodeFromTemplate(models, template, codeGenRunner.WorkingFolder, opts.OutputFile, opts.ExtendedProperties);
            Logger.Log(LogLevel.Info, $"Enums generated file: {opts.OutputFile}");

            if (errors.Count > 0)
            {
                Console.WriteLine($"\n\nEncountered {errors.Count} Errors");
                Console.ForegroundColor = ConsoleColor.Red;
                foreach (var err in errors)
                {
                    Console.WriteLine(err);
                }

                Console.ResetColor();
            }
        }
コード例 #14
0
        public override void Execute(AppOptionInfo opts, CodeGenRunner codeGenRunner)
        {
            var codeMapFile = GetCodeMapFile(opts);
            var map         = MapConfig.Create(codeMapFile, true);

            map.Settings.AssemblyName         = opts.AssemblyName;
            map.Settings.Namespace            = opts.Namespace;
            map.Settings.AdditionalNamespaces = codeGenRunner.Settings.AdditionalNamespaces;

            var providerFactory = new ProviderFactory();

            var importRdbms = GetRdbms(opts.ImportSqlDialect);
            var exportRdbms = GetRdbms(opts.ExportSqlDialect);

            var  dbConnector = providerFactory.CreateDbConnector(importRdbms, opts.ConnectionString);
            bool exportToxml = string.IsNullOrWhiteSpace(opts.TemplateName);

            if (!exportToxml && string.IsNullOrWhiteSpace(opts.TemplateName))
            {
                throw new GoliathDataException("Template file to use is required for generate operation. Please make sure that -in=\"Template_File_name.razt\" argument is passed in.");
            }

            var template = Path.Combine(codeGenRunner.TemplateFolder, opts.TemplateName ?? "");

            if (!exportToxml && !File.Exists(template))
            {
                throw new GoliathDataException($"template file {template} not found.");
            }

            if (string.IsNullOrWhiteSpace(opts.OutputFile))
            {
                throw new GoliathDataException("Output file is required for generate operation. Please make sure that -out=\"YOUR_FILE.EXT\" argument is passed in.");
            }

            var exporter = new DataExporterAdapter(providerFactory.CreateDialect(importRdbms), providerFactory.CreateDialect(exportRdbms),
                                                   dbConnector, new TypeConverterStore());

            List <string>    errors       = new List <string>();
            List <EntityMap> mapsToImport = new List <EntityMap>();

            if (!string.IsNullOrWhiteSpace(opts.Include))
            {
                var split = opts.Include.Split(new string[] { ",", "|" }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var s in split)
                {
                    if (s.StartsWith("*"))
                    {
                        var q = map.EntityConfigs.Where(c => c.Name.EndsWith(s.Trim().Replace("*", string.Empty))).ToList();
                        if (q.Count > 0)
                        {
                            mapsToImport.AddRange(q);
                        }
                    }

                    if (s.EndsWith("*"))
                    {
                        var q = map.EntityConfigs.Where(c => c.Name.StartsWith(s.Trim().Replace("*", string.Empty))).ToList();
                        if (q.Count > 0)
                        {
                            mapsToImport.AddRange(q);
                        }
                    }

                    var query = map.EntityConfigs.Where(c => c.Name.Equals(s.Trim()));
                    mapsToImport.AddRange(query);
                }
            }
            else
            {
                string[] split = new string[] { };
                if (!string.IsNullOrWhiteSpace(opts.Excluded))
                {
                    split = opts.Excluded.Split(new string[] { ",", "|" }, StringSplitOptions.RemoveEmptyEntries);
                }

                foreach (var mapEntityConfig in map.EntityConfigs)
                {
                    if (IsExcluded(mapEntityConfig.Name, split))
                    {
                        continue;
                    }
                    mapsToImport.Add(mapEntityConfig);
                }
            }

            var files = new List <string>();

            foreach (var entityMap in mapsToImport)
            {
                try
                {
                    var data = exporter.Export(entityMap, opts.ExportIdentityColumn, opts.ExportDatabaseGeneratedColumns);
                    if (data == null || data.DataBag.Count == 0)
                    {
                        continue;
                    }

                    if (exportToxml)
                    {
                        ExportToXml(data, opts, entityMap, codeGenRunner, files);
                    }
                    else
                    {
                        ExportToSql(data, opts, entityMap, codeGenRunner, template, files);
                    }
                }
                catch (Exception ex)
                {
                    errors.Add($"Error table [{entityMap.TableName}]: {ex}");
                }
            }

            if (errors.Count > 0)
            {
                Logger.Log(LogLevel.Warning, $"\n\nEncountered {errors.Count} Errors");
                Console.ForegroundColor = ConsoleColor.Red;
                foreach (var err in errors)
                {
                    Logger.Log(LogLevel.Error, err);
                }

                throw new Exception($"Export completed with {errors.Count} errors.");
            }

            if (opts.Compress)
            {
                var dbName = FileHelperMethods.GetDatabaseNameFromConnectionString(opts.ConnectionString);
                Compress(opts, $"{dbName}_exports.zip", files);
                DeleteAll(files);
            }
        }