/- Copyright (c) 2017 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Gabriel Ebner, Sebastian Ullrich, Mac Malone -/ import Lake.Util.Git import Lake.Util.Sugar import Lake.Config.Package import Lake.Config.Workspace import Lake.Load.Config namespace Lake open Git System /-- The default module of an executable in `std` package. -/ def defaultExeRoot : Name := `Main /-- `elan` toolchain file name -/ def toolchainFileName : FilePath := "lean-toolchain" def gitignoreContents := s!"/{defaultBuildDir} /{defaultPackagesDir}/* !/{defaultPackagesDir}/{defaultManifestFileName} " def libFileContents := s!"def hello := \"world\"" def mainFileName : FilePath := s!"{defaultExeRoot}.lean" def mainFileContents (libRoot : Name) := s!"import {libRoot} def main : IO Unit := IO.println s!\"Hello, \{hello}!\" " def exeFileContents := s!"def main : IO Unit := IO.println s!\"Hello, world!\" " def stdConfigFileContents (pkgName : Name) (root : Name) := s!"import Lake open Lake DSL package {pkgName} \{ -- add package configuration options here } lean_lib {root} \{ -- add library configuration options here } @[defaultTarget] lean_exe {pkgName} \{ root := `Main } " def exeConfigFileContents (pkgName : Name) (exeRoot : Name) := s!"import Lake open Lake DSL package {pkgName} \{ -- add package configuration options here } @[defaultTarget] lean_exe {exeRoot} \{ -- add executable configuration options here } " def libConfigFileContents (pkgName : Name) (libRoot : Name) := s!"import Lake open Lake DSL package {pkgName} \{ -- add package configuration options here } @[defaultTarget] lean_lib {libRoot} \{ -- add library configuration options here } " def mathConfigFileContents (pkgName : Name) (libRoot : Name) := s!"import Lake open Lake DSL package {pkgName} \{ -- add any package configuration options here } require mathlib from git \"https://github.com/leanprover-community/mathlib4.git\" @[defaultTarget] lean_lib {libRoot} \{ -- add any library configuration options here } " /-- The options for the template argument to `initPkg`. -/ inductive InitTemplate | std | exe | lib | math deriving Repr, DecidableEq def InitTemplate.parse? : String → Option InitTemplate | "std" => some .std | "exe" => some .exe | "lib" => some .lib | "math" => some .math | _ => none def InitTemplate.configFileContents (pkgName root : Name) : InitTemplate → String | .std => stdConfigFileContents pkgName root | .lib => libConfigFileContents pkgName root | .exe => exeConfigFileContents pkgName root | .math => mathConfigFileContents pkgName root instance : Inhabited InitTemplate := ⟨.std⟩ /-- Initialize a new Lake package in the given directory with the given name. -/ def initPkg (dir : FilePath) (name : String) (tmp : InitTemplate) : LogIO PUnit := do let pkgName := name.decapitalize.toName -- determine the name to use for the root -- use upper camel case unless the specific module name already exists let (root, rootFile, rootExists) ← do let root := name.toName let rootFile := Lean.modToFilePath dir root "lean" let rootExists ← rootFile.pathExists if tmp = .exe || rootExists then pure (root, rootFile, rootExists) else let root := toUpperCamelCase root let rootFile := Lean.modToFilePath dir root "lean" pure (root, rootFile, ← rootFile.pathExists) -- write default configuration file let configFile := dir / defaultConfigFile if (← configFile.pathExists) then error "package already initialized" IO.FS.writeFile configFile <| tmp.configFileContents pkgName root -- write example code if the files do not already exist if tmp = .exe then unless (← rootFile.pathExists) do IO.FS.writeFile rootFile exeFileContents else if !rootExists then IO.FS.createDirAll rootFile.parent.get! IO.FS.writeFile rootFile libFileContents if tmp = .std then let mainFile := dir / mainFileName unless (← mainFile.pathExists) do IO.FS.writeFile mainFile <| mainFileContents root -- write Lean's toolchain to file (if it has one) for `elan` if Lean.toolchain ≠ "" then IO.FS.writeFile (dir / toolchainFileName) <| Lean.toolchain ++ "\n" -- update `.gitignore` with additional entries for Lake let h ← IO.FS.Handle.mk (dir / ".gitignore") IO.FS.Mode.append (bin := false) h.putStr gitignoreContents -- initialize a `.git` repository if none already unless (← FilePath.isDir <| dir / ".git") do let repo := GitRepo.mk dir try repo.quietInit unless upstreamBranch = "master" do repo.checkoutBranch upstreamBranch else logWarning "failed to initialize git repository" def init (pkgName : String) (tmp : InitTemplate) : LogIO PUnit := initPkg "." pkgName tmp def new (pkgName : String) (tmp : InitTemplate) : LogIO PUnit := do let dirName := pkgName.map fun chr => if chr == '.' then '-' else chr IO.FS.createDir dirName initPkg dirName pkgName tmp