136 lines
7.0 KiB
C#
136 lines
7.0 KiB
C#
using System.CommandLine;
|
|
using MycroForge.CLI.Commands.Interfaces;
|
|
using MycroForge.CLI.Features;
|
|
|
|
namespace MycroForge.CLI.Commands;
|
|
|
|
public partial class MycroForge
|
|
{
|
|
#region GitIgnore
|
|
|
|
private static readonly string[] GitIgnore =
|
|
[
|
|
"# Byte-compiled / optimized / DLL files", "__pycache__/", "*.py[cod]", "*$py.class", "# C extensions",
|
|
"*.so", "# Distribution / packaging", ".Python", "build/", "develop-eggs/", "dist/", "downloads/", "eggs/",
|
|
".eggs/", "lib/", "lib64/", "parts/", "sdist/", "var/", "wheels/", "share/python-wheels/", "*.egg-info/",
|
|
".installed.cfg", "*.egg", "MANIFEST", "# PyInstaller",
|
|
"# Usually these files are written by a python script from a template",
|
|
"# before PyInstaller builds the exe, so as to inject date/other infos into it.", "*.manifest", "*.spec",
|
|
"# Installer logs", "pip-log.txt", "pip-delete-this-directory.txt", "# Unit test / coverage reports",
|
|
"htmlcov/", ".tox/", ".nox/", ".coverage", ".coverage.*", ".cache", "nosetests.xml", "coverage.xml",
|
|
"*.cover", "*.py,cover", ".hypothesis/", ".pytest_cache/", "cover/", "# Translations", "*.mo", "*.pot",
|
|
"# Django stuff:", "*.log", "local_settings.py", "db.sqlite3", "db.sqlite3-journal", "# Flask stuff:",
|
|
"instance/", ".webassets-cache", "# Scrapy stuff:", ".scrapy", "# Sphinx documentation", "docs/_build/",
|
|
"# PyBuilder", ".pybuilder/", "target/", "# Jupyter Notebook", ".ipynb_checkpoints", "# IPython",
|
|
"profile_default/", "ipython_config.py", "# pyenv",
|
|
"# For a library or package, you might want to ignore these files since the code is",
|
|
"# intended to run in multiple environments; otherwise, check them in:", "# .python-version", "# pipenv",
|
|
"# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.",
|
|
"# However, in case of collaboration, if having platform-specific dependencies or dependencies",
|
|
"# having no cross-platform support, pipenv may install dependencies that don't work, or not",
|
|
"# install all needed dependencies.", "#Pipfile.lock", "# poetry",
|
|
"# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.",
|
|
"# This is especially recommended for binary packages to ensure reproducibility, and is more",
|
|
"# commonly ignored for libraries.",
|
|
"# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control",
|
|
"#poetry.lock", "# pdm",
|
|
"# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.",
|
|
"#pdm.lock",
|
|
"# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it",
|
|
"# in version control.", "# https://pdm.fming.dev/#use-with-ide", ".pdm.toml",
|
|
"# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm", "__pypackages__/",
|
|
"# Celery stuff", "celerybeat-schedule", "celerybeat.pid", "# SageMath parsed files", "*.sage.py",
|
|
"# Environments", ".env", ".venv", "env/", "venv/", "ENV/", "env.bak/", "venv.bak/",
|
|
"# Spyder project settings", ".spyderproject", ".spyproject", "# Rope project settings", ".ropeproject",
|
|
"# mkdocs documentation", "/site", "# mypy", ".mypy_cache/", ".dmypy.json", "dmypy.json",
|
|
"# Pyre type checker", ".pyre/", "# pytype static type analyzer", ".pytype/", "# Cython debug symbols",
|
|
"cython_debug/", "# PyCharm",
|
|
"# JetBrains specific template is maintained in a separate JetBrains.gitignore that can",
|
|
"# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore",
|
|
"# and can be added to the global gitignore or merged into this file. For a more nuclear",
|
|
"# option (not recommended) you can uncomment the following to ignore the entire idea folder.", "#.idea/"
|
|
];
|
|
|
|
#endregion
|
|
|
|
public class Init : Command, ISubCommandOf<MycroForge>
|
|
{
|
|
private static readonly string[] DefaultFeatures =
|
|
[
|
|
Features.Git.FeatureName,
|
|
Features.Api.FeatureName,
|
|
Features.Orm.FeatureName
|
|
];
|
|
|
|
private static readonly Argument<string> NameArgument =
|
|
new(name: "name", description: "The name of your project");
|
|
|
|
private static readonly Option<IEnumerable<string>> WithoutOption =
|
|
new Option<IEnumerable<string>>(name: "--without", description: "Features to exclude")
|
|
{
|
|
AllowMultipleArgumentsPerToken = true
|
|
}.FromAmong(DefaultFeatures);
|
|
|
|
private readonly ProjectContext _context;
|
|
private readonly List<IFeature> _features;
|
|
|
|
public Init(ProjectContext context, IEnumerable<IFeature> features) :
|
|
base("init", "Initialize a new project")
|
|
{
|
|
_context = context;
|
|
_features = features.ToList();
|
|
|
|
AddArgument(NameArgument);
|
|
AddOption(WithoutOption);
|
|
this.SetHandler(ExecuteAsync, NameArgument, WithoutOption);
|
|
}
|
|
|
|
private async Task ExecuteAsync(string name, IEnumerable<string> without)
|
|
{
|
|
// Validate excluded features
|
|
var withoutList = without.ToList();
|
|
foreach (var feature in withoutList)
|
|
if (_features.All(f => f.Name != feature))
|
|
throw new Exception($"Feature {feature} does not exist.");
|
|
|
|
// Create the project directory and change the directory for the ProjectContext
|
|
var projectRoot = await CreateDirectory(name);
|
|
_context.ChangeDirectory(projectRoot);
|
|
|
|
// Create the config file and initialize the config
|
|
await _context.CreateFile("m4g.json", "{}");
|
|
|
|
// Create the entrypoint file
|
|
await _context.CreateFile("main.py");
|
|
|
|
// Create the default .gitignore folder
|
|
await _context.CreateFile(".gitignore", GitIgnore);
|
|
|
|
// Create the venv
|
|
await _context.Bash($"python3 -m venv {Path.Combine(projectRoot, ".venv")}");
|
|
|
|
// Initialize default features
|
|
foreach (var feature in _features.Where(f => DefaultFeatures.Contains(f.Name)))
|
|
if (!withoutList.Contains(feature.Name))
|
|
await feature.ExecuteAsync(_context);
|
|
|
|
Console.WriteLine($"Directory {projectRoot} was successfully initialized");
|
|
}
|
|
|
|
private async Task<string> CreateDirectory(string name)
|
|
{
|
|
var directory = Path.Combine(Directory.GetCurrentDirectory(), name);
|
|
|
|
if (Directory.Exists(directory))
|
|
throw new Exception($"Directory {directory} already exists.");
|
|
|
|
Console.WriteLine($"Creating directory {directory}");
|
|
|
|
Directory.CreateDirectory(directory);
|
|
|
|
await _context.Bash($"chmod -R 777 {directory}");
|
|
|
|
return directory;
|
|
}
|
|
}
|
|
} |