summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/support
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/support')
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/TODO4
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/build.sbt4
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/resources/TLCockpit/spinner-small.gifbin0 -> 16225 bytes
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/resources/TLCockpit/spinner.gifbin0 -> 60549 bytes
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/resources/logback.xml11
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala530
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/LocationDialog.scala37
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/OptionsDialog.scala13
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/PaperDialog.scala13
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/PkgInfoDialog.scala44
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/TLDisplayClasses.scala6
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/Utils.scala6
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/JsonProtocol.scala7
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsTools.scala5
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLClasses.scala19
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala37
-rw-r--r--Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/package.scala5
17 files changed, 553 insertions, 188 deletions
diff --git a/Master/texmf-dist/source/support/tlcockpit/TODO b/Master/texmf-dist/source/support/tlcockpit/TODO
new file mode 100644
index 00000000000..8597b267987
--- /dev/null
+++ b/Master/texmf-dist/source/support/tlcockpit/TODO
@@ -0,0 +1,4 @@
+TODO
+====
+(see TODOs in the code)
+
diff --git a/Master/texmf-dist/source/support/tlcockpit/build.sbt b/Master/texmf-dist/source/support/tlcockpit/build.sbt
index 032d4016c04..5f3770f7930 100644
--- a/Master/texmf-dist/source/support/tlcockpit/build.sbt
+++ b/Master/texmf-dist/source/support/tlcockpit/build.sbt
@@ -1,11 +1,13 @@
name := "tlcockpit"
-version := "0.7"
+version := "0.8"
scalaVersion := "2.12.3"
libraryDependencies += "org.scalafx" % "scalafx_2.12" % "8.0.102-R11"
libraryDependencies += "io.spray" %% "spray-json" % "1.3.3"
+libraryDependencies += "com.typesafe.scala-logging" %% "scala-logging" % "3.7.2"
+libraryDependencies += "ch.qos.logback" % "logback-classic" % "1.2.3"
mainClass in assembly := Some("TLCockpit.ApplicationMain")
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/resources/TLCockpit/spinner-small.gif b/Master/texmf-dist/source/support/tlcockpit/src/main/resources/TLCockpit/spinner-small.gif
new file mode 100644
index 00000000000..10dfdccdbd4
--- /dev/null
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/resources/TLCockpit/spinner-small.gif
Binary files differ
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/resources/TLCockpit/spinner.gif b/Master/texmf-dist/source/support/tlcockpit/src/main/resources/TLCockpit/spinner.gif
new file mode 100644
index 00000000000..bff38ea7a93
--- /dev/null
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/resources/TLCockpit/spinner.gif
Binary files differ
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/resources/logback.xml b/Master/texmf-dist/source/support/tlcockpit/src/main/resources/logback.xml
new file mode 100644
index 00000000000..ee899bf75de
--- /dev/null
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/resources/logback.xml
@@ -0,0 +1,11 @@
+<configuration>
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d{HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <root level="info">
+ <appender-ref ref="STDOUT" />
+ </root>
+</configuration> \ No newline at end of file
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala
index f37dc10806e..67b60576944 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/ApplicationMain.scala
@@ -1,11 +1,13 @@
// TLCockpit
-// Copyright 2017 Norbert Preining
+// Copyright 2017-2018 Norbert Preining
// Licensed according to GPLv3+
//
// Front end for tlmgr
package TLCockpit
+import javafx.scene.Node
+
import TLCockpit.Utils._
import TeXLive._
@@ -13,6 +15,7 @@ import scala.collection.{immutable, mutable}
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.{Future, Promise, SyncVar}
import scala.concurrent.ExecutionContext.Implicits.global
+import scala.io.Source
import scala.util.{Failure, Success}
import scala.sys.process._
import scalafx.beans.property.BooleanProperty
@@ -47,11 +50,40 @@ import scalafx.collections.ObservableMap
import spray.json._
import TeXLive.JsonProtocol._
+// logging
+import com.typesafe.scalalogging.LazyLogging
+import ch.qos.logback.classic.{Level,Logger}
+import org.slf4j.LoggerFactory
-object ApplicationMain extends JFXApp {
+object ApplicationMain extends JFXApp with LazyLogging {
val version: String = getClass.getPackage.getImplementationVersion
+ // parse command line arguments
+ // nothing => INFO
+ // -q WARN -qq ERROR
+ // -d => DEBUG -dd => TRACE
+ val cmdlnlog: Int = parameters.unnamed.map( {
+ case "-d" => Level.DEBUG_INT
+ case "-dd" => Level.TRACE_INT
+ case "-q" => Level.WARN_INT
+ case "-qq" => Level.ERROR_INT
+ case _ => -1
+ } ).foldLeft(Level.OFF_INT)(scala.math.min)
+ if (cmdlnlog == -1) {
+ // Unknown log level has been passed in, error out
+ Console.err.println("Unsupported command line argument passed in, terminating.")
+ Platform.exit()
+ sys.exit(0)
+ }
+ // if nothing has been passed on the command line, use INFO
+ val newloglevel: Int = if (cmdlnlog == Level.OFF_INT) Level.INFO_INT else cmdlnlog
+
+ LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME).
+ asInstanceOf[Logger].setLevel(Level.toLevel(newloglevel))
+
+ logger.trace("starting program tlcockpit")
+
var tlmgrBusy = BooleanProperty(false)
// necessary action when Window is closed with X or some other operation
@@ -61,8 +93,24 @@ object ApplicationMain extends JFXApp {
val iconImage = new Image(getClass.getResourceAsStream("tlcockpit-48.jpg"))
val logoImage = new Image(getClass.getResourceAsStream("tlcockpit-128.jpg"))
+ val busyImage = new Image(getClass.getResourceAsStream("spinner-small.gif"))
+ val msgFont = new Font(30f)
+
+ val busySpinner: ImageView = new ImageView(busyImage) {
+ // scaleX = 0.3
+ // scaleY = 0.3
+ }
+
+ def SpinnerPlaceHolder(txt: String): Node = {
+ val tmp = new Label(txt)
+ tmp.wrapText = true
+ tmp.opacity = 0.4f
+ tmp.font = msgFont
+ tmp.graphic = busySpinner
+ tmp
+ }
- val tlpkgs: ObservableMap[String, TLPackage] = ObservableMap[String,TLPackage]()
+ val tlpkgs: ObservableMap[String, TLPackageShort] = ObservableMap[String,TLPackageShort]()
val pkgs: ObservableMap[String, TLPackageDisplay] = ObservableMap[String, TLPackageDisplay]()
val upds: ObservableMap[String, TLUpdateDisplay] = ObservableMap[String, TLUpdateDisplay]()
val bkps: ObservableMap[String, Map[String, TLBackupDisplay]] = ObservableMap[String, Map[String,TLBackupDisplay]]() // pkgname -> (version -> TLBackup)*
@@ -104,7 +152,7 @@ object ApplicationMain extends JFXApp {
})
val update_all_menu: MenuItem = new MenuItem("Update all") {
- val cmd = "--all" + {
+ val cmd: String = "--all" + {
if (disable_auto_install) " --no-auto-install" else "" } + {
if (disable_auto_removal) " --no-auto-remove" else "" } + {
if (enable_reinstall_forcible) " --reinstall-forcibly-removed" else "" }
@@ -147,10 +195,29 @@ object ApplicationMain extends JFXApp {
cmdline.onKeyPressed = {
(ae: KeyEvent) => if (ae.code == KeyCode.Enter) callback_run_cmdline()
}
- val outputLine = new SyncVar[String]
- val errorLine = new SyncVar[String]
+
+ // read the perl dump of ctan mirrors by converting it to JSON code and parsing it
+ def parse_ctan_mirrors(tlroot: String): Map[String,Map[String,Seq[String]]] = {
+ try {
+ val fileName = tlroot + "/tlpkg/installer/ctan-mirrors.pl"
+ val foo: String = Source.fromFile(fileName).getLines.mkString("")
+ val jsonMirrorString = foo.substring(10).replace("=>", ":").replace("""'""", "\"").replace(";", "")
+ val ast = jsonMirrorString.parseJson
+ ast.convertTo[Map[String, Map[String, Map[String, Int]]]].map {
+ contpair =>
+ (contpair._1, contpair._2.map {
+ countrypair => (countrypair._1, countrypair._2.keys.toSeq)
+ })
+ }
+ } catch { case e: Exception =>
+ logText.append("Cannot find or parse ctan-mirrors.pl")
+ logger.debug("Cannot find or parse ctan-mirrors.pl")
+ Map[String,Map[String,Seq[String]]]()
+ }
+ }
+
def callback_quit(): Unit = {
tlmgr.cleanup()
Platform.exit()
@@ -199,22 +266,29 @@ object ApplicationMain extends JFXApp {
OutputBufferIndex = 0
}
- def callback_run_external(s: String, unbuffered: Boolean = true): Unit = {
+ def callback_run_external(ss: Array[String], unbuffered: Boolean = true): Unit = {
outputText.clear()
// logText.clear()
outerrpane.expanded = true
outerrtabs.selectionModel().select(0)
- outputText.append(s"Running $s" + (if (unbuffered) " (unbuffered)" else " (buffered)"))
+ // outputText.append(s"Running ${ss.mkString(" ")}" + (if (unbuffered) " (unbuffered)" else " (buffered)"))
val foo = Future {
- s ! ProcessLogger(
- line => if (unbuffered) Platform.runLater( outputText.append(line) )
- else OutputBuffer.synchronized( OutputBuffer.append(line + "\n") ),
- line => Platform.runLater( logText.append(line) )
- )
+ ss.foreach { s =>
+ Platform.runLater {
+ outputText.append(s"Running ${s}" + (if (unbuffered) " (unbuffered)" else " (buffered)"))
+ actionLabel.text = s"[${s}]"
+ }
+ s ! ProcessLogger(
+ line => if (unbuffered) Platform.runLater(outputText.append(line))
+ else OutputBuffer.synchronized(OutputBuffer.append(line + "\n")),
+ line => Platform.runLater(logText.append(line))
+ )
+ }
}
foo.onComplete {
case Success(ret) =>
Platform.runLater {
+ actionLabel.text = ""
outputText.append(OutputBuffer.slice(OutputBufferIndex,OutputBuffer.length).mkString(""))
outputText.append("Completed")
reset_output_buffer()
@@ -222,11 +296,12 @@ object ApplicationMain extends JFXApp {
}
case Failure(t) =>
Platform.runLater {
+ actionLabel.text = ""
outputText.append(OutputBuffer.slice(OutputBufferIndex,OutputBuffer.length).mkString(""))
outputText.append("Completed")
reset_output_buffer()
outputfield.scrollTop = Double.MaxValue
- errorText.append("An ERROR has occurred running $s: " + t.getMessage)
+ errorText.append(s"An ERROR has occurred running one of ${ss.mkString(" ")}: " + t.getMessage)
errorfield.scrollTop = Double.MaxValue
outerrpane.expanded = true
outerrtabs.selectionModel().select(2)
@@ -240,14 +315,36 @@ object ApplicationMain extends JFXApp {
title = "About TLCockpit"
graphic = new ImageView(logoImage)
headerText = "TLCockpit version " + version + "\n\nManage your TeX Live with speed!"
- contentText = "Copyright 2017 Norbert Preining\nLicense: GPL3+\nSources: https://github.com/TeX-Live/tlcockpit"
+ contentText = "Copyright 2017-2018 Norbert Preining\nLicense: GPL3+\nSources: https://github.com/TeX-Live/tlcockpit"
}.showAndWait()
}
- def set_line_update_function(mode: String) = {
+ // Output of update --self
+ /*
+tlmgr>
+update --self
+location-url /home/norbert/public_html/tlnet /home/norbert/public_html/tlcritical /home/norbert/Domains/server/texlive.info/contrib/2017 /home/norbert/public_html/tltexjp
+total-bytes 381087
+end-of-header
+texlive.infra u 4629 46295 381087 ??:?? ??:?? tlcritical - -
+end-of-updates
+STDERR running mktexlsr ...
+STDERR done running mktexlsr.
+STDERR running mtxrun --generate ...
+STDERR done running mtxrun --generate.
+OK
+STDOUT (with patch STDERR) tlmgr has been updated, restarting!
+protocol 1
+tlmgr>
+
+ The problem with the update function lies in the
+ protocol 1
+ which is not accepted/expected by the update function!
+ */
+ def set_line_update_function(mode: String): Unit = {
var prevName = ""
stdoutLineUpdateFunc = (l:String) => {
- // println("DEBUG line update: " + l + "=")
+ logger.trace("DEBUG line update: " + l + "=")
l match {
case u if u.startsWith("location-url") => None
case u if u.startsWith("total-bytes") => None
@@ -286,10 +383,21 @@ object ApplicationMain extends JFXApp {
packageTable.refresh()
}
if (u.startsWith("end-of-updates")) {
+ if (mode == "update") {
+ Platform.runLater {
+ updateTable.placeholder = SpinnerPlaceHolder("Post actions running")
+ actionLabel.text = "[post actions running]"
+ }
+ }
// nothing to be done, all has been done above
- // println("DEBUG got end of updates")
+ logger.debug("DEBUG got end of updates")
+ // } else if (u.startsWith("protocol ")) {
+ // logger.debug("Got protocol line, seems tlmgr got updated and restarted!")
+ // // nothing else to be done
+ // } else if (u.startsWith("tlmgr has been updated, restarting")) {
+ // logger.debug("tlmgr got updated and restarted, ignoring output")
} else {
- // println("DEBUG getting update line")
+ logger.debug("DEBUG getting update line")
prevName = if (mode == "update") {
val foo = parse_one_update_line(l)
val pkgname = foo.name.value
@@ -315,10 +423,14 @@ object ApplicationMain extends JFXApp {
}
def callback_update(s: String): Unit = {
+ val prevph = updateTable.placeholder.value
set_line_update_function("update")
- val cmd = if (s == "--self") "update --self" else s"update $s"
+ val cmd = if (s == "--self") "update --self --no-restart" else s"update $s"
tlmgr_send(cmd, (a,b) => {
stdoutLineUpdateFunc = defaultStdoutLineUpdateFunc
+ Platform.runLater {
+ updateTable.placeholder = prevph
+ }
if (s == "--self") {
reinitialize_tlmgr()
// this doesn't work seemingly
@@ -329,11 +441,15 @@ object ApplicationMain extends JFXApp {
def callback_remove(pkg: String): Unit = {
set_line_update_function("remove")
- tlmgr_send(s"remove $pkg", (_, _) => { stdoutLineUpdateFunc = defaultStdoutLineUpdateFunc })
+ tlmgr_send(s"remove $pkg", (_, _) => {
+ stdoutLineUpdateFunc = defaultStdoutLineUpdateFunc
+ })
}
def callback_install(pkg: String): Unit = {
set_line_update_function("install")
- tlmgr_send(s"install $pkg", (_,_) => { stdoutLineUpdateFunc = defaultStdoutLineUpdateFunc })
+ tlmgr_send(s"install $pkg", (_,_) => {
+ stdoutLineUpdateFunc = defaultStdoutLineUpdateFunc
+ })
}
@@ -342,6 +458,7 @@ object ApplicationMain extends JFXApp {
tlpkgs(str).lrev = rev.toLong
pkgs(str).lrev = ObjectProperty[Int](rev.toInt)
packageTable.refresh()
+ Platform.runLater { actionLabel.text = "[running post actions]" }
})
}
@@ -352,7 +469,7 @@ object ApplicationMain extends JFXApp {
case ObservableMap.Remove(k, v) => k.toString == "root"
}
if (doit) {
- // println("DEBUG bkps.onChange called new length = " + bkps.keys.toArray.length)
+ logger.debug("DEBUG bkps.onChange called new length = " + bkps.keys.toArray.length)
val newroot = new TreeItem[TLBackupDisplay](new TLBackupDisplay("root", "", "")) {
children = bkps
.filter(_._1 != "root")
@@ -461,7 +578,7 @@ object ApplicationMain extends JFXApp {
case ObservableMap.Remove(k,v) => false
}
if (doit) {
- // println("DEBUG: entering pkgs.onChange")
+ logger.debug("DEBUG: entering pkgs.onChange")
// val pkgbuf: ArrayBuffer[TLPackageDisplay] = ArrayBuffer.empty[TLPackageDisplay]
val pkgbuf = scala.collection.mutable.Map.empty[String, TLPackageDisplay]
val binbuf = scala.collection.mutable.Map.empty[String, ArrayBuffer[TLPackageDisplay]]
@@ -499,9 +616,9 @@ object ApplicationMain extends JFXApp {
if (!pkgbuf.contains(p._1)) {
if (p._2.length > 1) {
errorText += "THAT SHOULD NOT HAPPEN: >>" + p._1 + "<< >>" + p._2.length + "<<"
- // p._2.foreach(f => println("-> " + f.name.value))
+ p._2.foreach(f => logger.trace("-> " + f.name.value))
} else {
- // println("DEBUG Moving " + p._2.head.name.value + " up to pkgbuf " + p._1)
+ logger.trace("DEBUG Moving " + p._2.head.name.value + " up to pkgbuf " + p._1)
pkgbuf(p._2.head.name.value) = p._2.head
// TODO will this work out with the foreach loop above???
binbuf -= p._1
@@ -516,7 +633,7 @@ object ApplicationMain extends JFXApp {
colbuf(pkg._1) = ArrayBuffer[TLPackageDisplay]()
// TODO we need to deal with packages that get removed!!!
// for now just make sure we don't add them here!
- colbuf(pkg._1) ++= foo.filter(pkgbuf.contains(_)).map(pkgbuf(_))
+ colbuf(pkg._1) ++= foo.filter(pkgbuf.contains).map(pkgbuf(_))
}
} else if (pkg._1 == "root") {
// do nothing
@@ -531,7 +648,7 @@ object ApplicationMain extends JFXApp {
view_pkgs_by_names(pkgbuf, binbuf)
else
view_pkgs_by_collections(pkgbuf, binbuf, colbuf)
- // println("DEBUG: leaving pkgs.onChange before runLater")
+ logger.debug("DEBUG: leaving pkgs.onChange before runLater")
Platform.runLater {
packageTable.root = new TreeItem[TLPackageDisplay](new TLPackageDisplay("root", "0", "0", "", "0", "")) {
expanded = true
@@ -578,12 +695,8 @@ object ApplicationMain extends JFXApp {
}
def load_backups_update_bkps_view(): Unit = {
- val tmp = new Label("Loading backups, please wait ...")
- tmp.wrapText = true
- tmp.opacity = 0.4f
- tmp.font = new Font(30f)
val prevph = backupTable.placeholder.value
- backupTable.placeholder = tmp
+ backupTable.placeholder = SpinnerPlaceHolder("Loading backups")
tlmgr_send("restore --json", (status, lines) => {
val jsonAst = lines.mkString("").parseJson
val backups: Map[String, Map[String, TLBackupDisplay]] =
@@ -619,14 +732,13 @@ object ApplicationMain extends JFXApp {
trigger_update("pkgs")
}
+ /*
def load_tlpdb_update_pkgs_view():Unit = {
- val tmp = new Label("Loading database, please wait ...")
- tmp.wrapText = true
- tmp.opacity = 0.4f
- tmp.font = new Font(30f)
val prevph = packageTable.placeholder.value
- packageTable.placeholder = tmp
+ packageTable.placeholder = SpinnerPlaceHolder("Loading database")
tlmgr_send("info --json", (status, lines) => {
+ logger.debug(s"load tlpdb update pkgs: got status ${status}")
+ logger.trace(s"load tlpdb update pkgs: got lines = " + lines.head)
val jsonAst = lines.mkString("").parseJson
tlpkgs.clear()
tlpkgs ++= jsonAst.convertTo[List[TLPackage]].map { p => (p.name, p)}
@@ -634,9 +746,40 @@ object ApplicationMain extends JFXApp {
packageTable.placeholder = prevph
})
}
+ */
+
+ def load_tlpdb_update_pkgs_view_no_json():Unit = {
+ val prevph = packageTable.placeholder.value
+ packageTable.placeholder = SpinnerPlaceHolder("Loading database")
+ tlmgr_send("info --data name,localrev,remoterev,category,size,installed,depends,shortdesc", (status, lines) => {
+ logger.debug(s"load tlpdb update (no json) pkgs: got status ${status}")
+ logger.trace(s"load tlpdb update (no json) pkgs: got lines = " + lines.head)
+ val newtlpkgs: Map[String, TLPackageShort] = lines.map(l => {
+ val fields = l.split(",",8)
+ val pkgname = fields(0)
+ val shortdesc = fields(7).stripPrefix(""""""").stripSuffix(""""""").replaceAll("""\\"""",""""""")
+ val lrev = fields(1).toLong
+ val rrev = fields(2).toLong
+ val cat = fields(3)
+ val size = fields(4).toLong
+ val installed = fields(5) == "1"
+ val depends = fields(6).split(":").toList
+ TLPackageShort(pkgname, if (shortdesc == "") None else Some(shortdesc), lrev, rrev, cat, depends, installed, lrev > 0)
+ }).map{ p =>
+ logger.trace("Constructed TLPackage: " + p)
+ (p.name, p)
+ }.toMap
+ tlpkgs.clear()
+ tlpkgs ++= newtlpkgs
+ update_pkgs_view()
+ packageTable.placeholder = prevph
+ })
+ }
def parse_one_update_line(l: String): TLUpdateDisplay = {
+ logger.debug(s"Got update line >>${l}")
val fields = l.split("\t")
+ logger.debug(s"Splitting into ${fields}")
val pkgname = fields(0)
val status = fields(1) match {
case "d" => "Removed on server"
@@ -668,23 +811,17 @@ object ApplicationMain extends JFXApp {
}
def load_updates_update_upds_view(): Unit = {
- val tmp = new Label("Loading updates, please wait ...")
- tmp.wrapText = true
- tmp.opacity = 0.4f
- tmp.font = new Font(30f)
val prevph = updateTable.placeholder.value
- updateTable.placeholder = tmp
+ updateTable.placeholder = SpinnerPlaceHolder("Loading updates")
tlmgr_send("update --list", (status, lines) => {
- // println(s"DEBUG got updates length ${lines.length}")
- // println(s"DEBUG tlmgr last output = ${lines}")
- val newupds: Map[String, TLUpdateDisplay] = lines.filter { l =>
- l match {
- case u if u.startsWith("location-url") => false
- case u if u.startsWith("total-bytes") => false
- case u if u.startsWith("end-of-header") => false
- case u if u.startsWith("end-of-updates") => false
- case u => true
- }
+ logger.debug(s"got updates length ${lines.length}")
+ logger.trace(s"tlmgr last output = ${lines}")
+ val newupds: Map[String, TLUpdateDisplay] = lines.filter {
+ case u if u.startsWith("location-url") => false
+ case u if u.startsWith("total-bytes") => false
+ case u if u.startsWith("end-of-header") => false
+ case u if u.startsWith("end-of-updates") => false
+ case u => true
}.map { l =>
val foo = parse_one_update_line(l)
(foo.name.value, foo)
@@ -702,7 +839,7 @@ object ApplicationMain extends JFXApp {
}
def trigger_update(s:String): Unit = {
- // println("DEBUG: Triggering update of " + s)
+ logger.debug("DEBUG: Triggering update of " + s)
if (s == "pkgs") {
pkgs("root") = new TLPackageDisplay("root", "0", "0", "", "0", "")
} else if (s == "upds") {
@@ -767,15 +904,15 @@ object ApplicationMain extends JFXApp {
items = List(
new MenuItem("Update filename databases ...") {
onAction = (ae) => {
- callback_run_external("mktexlsr")
- callback_run_external("mtxrun --generate")
+ callback_run_external(Array("mktexlsr", "mtxrun --generate"))
+ // callback_run_external("mtxrun --generate")
}
},
// too many lines are quickly output -> GUI becomes hanging until
// all the callbacks are done - call fmtutil with unbuffered = false
- new MenuItem("Rebuild all formats ...") { onAction = (ae) => callback_run_external("fmtutil --sys --all", false) },
+ new MenuItem("Rebuild all formats ...") { onAction = (ae) => callback_run_external(Array("fmtutil --sys --all"), false) },
new MenuItem("Update font map database ...") {
- onAction = (ae) => callback_run_external("updmap --sys")
+ onAction = (ae) => callback_run_external(Array("updmap --sys"))
}
)
}
@@ -843,10 +980,10 @@ object ApplicationMain extends JFXApp {
val dg = new PaperDialog(paperconfs)
dg.showAndWait() match {
case Some(newPapers) =>
- // println(s"Got result ${newPapers}")
+ logger.debug(s"Got result ${newPapers}")
// collect changed settings
val changedPapers = newPapers.filter(p => currentPapers(p._1) != p._2)
- // println(s"Got changed papers ${changedPapers}")
+ logger.debug(s"Got changed papers ${changedPapers}")
changedPapers.foreach(p => {
tlmgr_send(s"paper ${p._1} paper ${p._2}", (_,_) => None)
})
@@ -856,6 +993,33 @@ object ApplicationMain extends JFXApp {
})
}
+ def callback_pkg_info(pkg: String) = {
+ tlmgr_send(s"info --json ${pkg}", (status, lines) => {
+ try {
+ val jsonAst = lines.mkString("").parseJson
+ val tlpkgs = jsonAst.convertTo[List[TLPackage]]
+ Platform.runLater {
+ new PkgInfoDialog(tlpkgs.head).showAndWait()
+ }
+ } catch {
+ case foo : spray.json.DeserializationException =>
+ new Alert(AlertType.Warning) {
+ initOwner(stage)
+ title = "Warning"
+ headerText = s"Cannot display information for ${pkg}"
+ contentText = s"We couldn't parse the output of\ntlmgr info --json ${pkg}\n"
+ }.showAndWait()
+ case bar : ArrayIndexOutOfBoundsException =>
+ new Alert(AlertType.Warning) {
+ initOwner(stage)
+ title = "Warning"
+ headerText = s"Cannot find information for ${pkg}"
+ contentText = s"We couldn't find information for ${pkg}\n"
+ }.showAndWait()
+ }
+ })
+ }
+
val optionsMenu: Menu = new Menu("Options") {
items = List(
new MenuItem("General ...") { onAction = (ae) => callback_general_options() },
@@ -868,9 +1032,6 @@ object ApplicationMain extends JFXApp {
new CheckMenuItem("Disable auto-removal of server-deleted packages") { disable = true } */
)
}
- val statusMenu: Menu = new Menu("Status: Idle") {
- disable = true
- }
val expertPane: TitledPane = new TitledPane {
text = "Experts only"
collapsible = true
@@ -933,12 +1094,15 @@ object ApplicationMain extends JFXApp {
colDesc.prefWidth.bind(table.width - colName.width - colLRev.width - colRRev.width - colSize.width - colStatus. width - 15)
table.prefHeight = 300
table.vgrow = Priority.Always
- table.placeholder = new Label("No updates available")
+ table.placeholder = new Label("No updates available") {
+ opacity = 0.4f
+ font = msgFont
+ }
table.showRoot = false
table.rowFactory = { _ =>
val row = new TreeTableRow[TLUpdateDisplay] {}
val infoMI = new MenuItem("Info") {
- onAction = (ae) => new PkgInfoDialog(row.item.value.name.value).showAndWait()
+ onAction = (ae) => callback_pkg_info(row.item.value.name.value)
}
val updateMI = new MenuItem("Update") {
onAction = (ae) => callback_update(row.item.value.name.value)
@@ -1001,7 +1165,7 @@ object ApplicationMain extends JFXApp {
table.rowFactory = { p =>
val row = new TreeTableRow[TLPackageDisplay] {}
val infoMI = new MenuItem("Info") {
- onAction = (ae) => new PkgInfoDialog(row.item.value.name.value).showAndWait()
+ onAction = (ae) => callback_pkg_info(row.item.value.name.value)
}
val installMI = new MenuItem("Install") {
onAction = (ae) => callback_install(row.item.value.name.value)
@@ -1052,7 +1216,7 @@ object ApplicationMain extends JFXApp {
val row = new TreeTableRow[TLBackupDisplay] {}
val ctm = new ContextMenu(
new MenuItem("Info") {
- onAction = (ae) => new PkgInfoDialog(row.item.value.name.value).showAndWait()
+ onAction = (ae) => callback_pkg_info(row.item.value.name.value)
},
new MenuItem("Restore") {
onAction = (ae) => callback_restore(row.item.value.name.value, row.item.value.rev.value)
@@ -1068,6 +1232,28 @@ object ApplicationMain extends JFXApp {
searchEntry.onKeyPressed = {
(ae: KeyEvent) => if (ae.code == KeyCode.Enter) update_pkgs_view()
}
+ val statusLabel = new Label("Idle")
+ val actionLabel = new Label("") {
+ hgrow = Priority.Always
+ maxWidth = Double.MaxValue
+ }
+ val statusBox = new HBox {
+ children = Seq(
+ new Label("Tlmgr status:") {
+ vgrow = Priority.Always
+ alignmentInParent = Pos.CenterLeft
+ },
+ statusLabel,
+ actionLabel
+ )
+ maxWidth = Double.MaxValue
+ hgrow = Priority.Always
+ alignment = Pos.Center
+ alignmentInParent = Pos.CenterLeft
+ padding = Insets(10)
+ spacing = 10
+ }
+
val searchBox = new HBox {
children = Seq(
new Label("Search:") {
@@ -1086,7 +1272,8 @@ object ApplicationMain extends JFXApp {
}
)
alignment = Pos.Center
- padding = Insets(10)
+ // do not add padding at the bottom as we have one from the status field
+ padding = Insets(10,10,0,10)
spacing = 10
}
val pkgsContainer = new VBox {
@@ -1120,21 +1307,27 @@ object ApplicationMain extends JFXApp {
val menuBar: MenuBar = new MenuBar {
useSystemMenuBar = true
// menus.addAll(mainMenu, optionsMenu, helpMenu)
- menus.addAll(mainMenu, pkgsMenu, toolsMenu, optionsMenu, statusMenu)
+ menus.addAll(mainMenu, pkgsMenu, toolsMenu, optionsMenu)
}
+ var updLoaded = false
+ var bckLoaded = false
pkgstabs.selectionModel().selectedItem.onChange(
(a,b,c) => {
if (a.value.text() == "Backups") {
- if (backupTable.root.value.children.length == 0)
+ if (!bckLoaded) {
load_backups_update_bkps_view()
- menuBar.menus = Seq(mainMenu, toolsMenu, optionsMenu, statusMenu)
+ bckLoaded = true
+ }
+ menuBar.menus = Seq(mainMenu, toolsMenu, optionsMenu)
} else if (a.value.text() == "Updates") {
// only update if not done already
- if (updateTable.root.value.children.length == 0)
+ if (!updLoaded) {
load_updates_update_upds_view()
- menuBar.menus = Seq(mainMenu, updMenu, toolsMenu, optionsMenu, statusMenu)
+ updLoaded = true
+ }
+ menuBar.menus = Seq(mainMenu, updMenu, toolsMenu, optionsMenu)
} else if (a.value.text() == "Packages") {
- menuBar.menus = Seq(mainMenu, pkgsMenu, toolsMenu, optionsMenu, statusMenu)
+ menuBar.menus = Seq(mainMenu, pkgsMenu, toolsMenu, optionsMenu)
}
}
)
@@ -1152,7 +1345,7 @@ object ApplicationMain extends JFXApp {
val topBox = menuBar
val centerBox = new VBox {
padding = Insets(10)
- children = List(pkgstabs, expertPane, outerrpane)
+ children = List(pkgstabs, statusBox, expertPane, outerrpane)
}
new BorderPane {
// padding = Insets(20)
@@ -1176,14 +1369,32 @@ object ApplicationMain extends JFXApp {
def initialize_tlmgr(): TlmgrProcess = {
tlmgrBusy.value = true
+ actionLabel.text = "[initializing tlmgr]"
+ // create new sync vars for each process
+ val outputLine = new SyncVar[String]
+ val errorLine = new SyncVar[String]
+
val tt = new TlmgrProcess(
- (s: String) => outputLine.put(s),
- (s: String) => errorLine.put(s)
+ (s: String) => {
+ logger.trace(s"outputline put ${s}")
+ outputLine.put(s)
+ },
+ (s: String) => {
+ logger.trace(s"errorline put ${s}")
+ errorLine.put(s)
+ }
)
+ if (!tt.start_process()) {
+ logger.debug("Cannot start tlmgr process, terminating!")
+ Platform.exit()
+ sys.exit(1)
+ }
+ logger.debug("initialize_tlmgr: sleeping after starting process")
+ Thread.sleep(1000)
/* val tlmgrMonitor = Future {
while (true) {
if (!tlmgr.isAlive) {
- println("TLMGR HAS DIED!!!!")
+ logger.debug("TLMGR HAS DIED!!!!")
// Platform.exit()
// sys.exit(1)
}
@@ -1194,25 +1405,39 @@ object ApplicationMain extends JFXApp {
val tlmgrOutput = ArrayBuffer[String]()
var tlmgrStatus = ""
var alive = true
+ logger.debug("initialize tlmgr: starting stdout reader thread")
while (alive) {
+ logger.trace("stdout reader before outputLine.take")
val s = outputLine.take
+ logger.trace("stdout reader after outputLine.take")
if (s == null) {
alive = false
- // println("GOT NULL from outputline tlmgr dead???")
+ logger.debug("got null from stdout, tlmgr seems to be terminated for restart")
+ if (!currentPromise.isCompleted) {
+ logger.debug(s"Fulfilling remaining open promise with ${tlmgrStatus} and ${tlmgrOutput.toArray.mkString}")
+ currentPromise.success((tlmgrStatus, tlmgrOutput.toArray))
+ }
+ tlmgrStatus = ""
+ tlmgrOutput.clear()
+ tlmgrBusy.value = false
} else {
- //println(s"DEBUG: got " + s)
+ logger.trace(s"DEBUG: got ==" + s + "==")
if (s == "OK") {
tlmgrStatus = s
} else if (s == "ERROR") {
tlmgrStatus = s
} else if (s == "tlmgr> ") {
- // println("DEBUG: fulfilling current promise!")
- currentPromise.success((tlmgrStatus, tlmgrOutput.toArray))
+ logger.trace(s"Fulfilling current promise with ${tlmgrStatus} and ${tlmgrOutput.toArray.mkString}!")
+ if (!currentPromise.isCompleted) {
+ currentPromise.success((tlmgrStatus, tlmgrOutput.toArray))
+ }
tlmgrStatus = ""
tlmgrOutput.clear()
tlmgrBusy.value = false
if (pendingJobs.nonEmpty) {
+ logger.debug("pending Job found!")
val nextCmd = pendingJobs.dequeue()
+ logger.debug(s"running ${nextCmd._1}")
tlmgr_run_one_cmd(nextCmd._1, nextCmd._2)
}
} else {
@@ -1221,31 +1446,26 @@ object ApplicationMain extends JFXApp {
}
}
}
+ logger.debug("initialize tlmgr: finishing stdout reader thread")
}
- tlmgrBusy.onChange({ Platform.runLater{ statusMenu.text = "Status: " + (if (tlmgrBusy.value) "Busy" else "Idle") }})
+ tlmgrBusy.onChange({
+ Platform.runLater {
+ statusLabel.text = if (tlmgrBusy.value) "Busy" else "Idle"
+ if (!tlmgrBusy.value)
+ actionLabel.text = ""
+ }
+ })
+
stdoutFuture.onComplete {
case Success(value) =>
- // println(s"tlmgr stdout reader terminated: ${value}")
- Platform.runLater {
- outerrpane.expanded = true
- outerrtabs.selectionModel().select(1)
- errorfield.scrollTop = Double.MaxValue
- logfield.scrollTop = Double.MaxValue
- new Alert(AlertType.Error) {
- initOwner(stage)
- title = "TeX Live Manager tlmgr has terminated"
- headerText = "TeX Live Manager tlmgr has terminated - we cannot continue"
- contentText = "Please inspect the debug output in the main window lower pane!"
- }.showAndWait()
- // Platform.exit()
- // sys.exit(1)
- }
+ logger.debug(s"tlmgr stdout reader terminated: ${value}")
case Failure(e) =>
- errorText += "lineUpdateFunc(stdout) thread got interrupted -- probably old tlmgr, ignoring it!"
- e.printStackTrace
+ logger.debug(s"tlmgr stdout reader terminated with error: ${e}")
}
+
val stderrFuture = Future {
var alive = true
+ logger.debug("initialize tlmgr: starting stderr reader thread")
while (alive) {
val s = errorLine.take
if (s == null)
@@ -1253,29 +1473,67 @@ object ApplicationMain extends JFXApp {
else
stderrLineUpdateFunc(s)
}
+ logger.debug("initialize tlmgr: finishing stderr reader thread")
}
stderrFuture.onComplete {
- case Success(value) => // println(s"tlmgr stderr reader terminated: ${value}")
+ case Success(value) =>
+ logger.debug(s"tlmgr stderr reader terminated: ${value}")
case Failure(e) =>
- errorText += "lineUpdateFunc(stderr) thread got interrupted -- probably old tlmgr, ignoring it!"
- e.printStackTrace
+ logger.debug(s"tlmgr stderr reader terminated with failure: ${e}")
}
+
tt
}
+ def tlmgr_post_init() = {
+
+ // check for tlmgr revision
+ tlmgr_send("version", (status,output) => {
+ logger.debug(s"Callback after version, got ${status} and ${output.mkString("\n")}")
+ output.foreach ( l => {
+ if (l.startsWith("revision ")) {
+ val tlmgrRev = l.stripPrefix("revision ")
+ if (tlmgrRev == "unknown") {
+ logger.debug("Unknown tlmgr revision, assuming git/svn version")
+ logText += "Unknown tlmgr revision, assuming git/svn version"
+ } else {
+ if (tlmgrRev.toInt < 45838) {
+ new Alert(AlertType.Error) {
+ initOwner(stage)
+ title = "TeX Live Manager tlmgr is too old"
+ headerText = "TeX Live Manager tlmgr is too old"
+ contentText = "Please update from the command line\nusing 'tlmgr update --self'\nTerminating!"
+ }.showAndWait()
+ callback_quit()
+ }
+ }
+ }
+ })
+ pkgs.clear()
+ upds.clear()
+ bkps.clear()
+ logger.debug("Before loading tlpdb")
+ load_tlpdb_update_pkgs_view_no_json()
+ logger.debug("after loading tlpdb")
+ })
+ }
+
def tlmgr_run_one_cmd(s: String, onCompleteFunc: (String, Array[String]) => Unit): Unit = {
currentPromise = Promise[(String, Array[String])]()
tlmgrBusy.value = true
+ actionLabel.text = s"[${s}]"
currentPromise.future.onComplete {
case Success((a, b)) =>
- // println("DEBUG current future completed!")
+ logger.debug("tlmgr run one cmd: current future completed!")
Platform.runLater {
+ logger.debug("tlmgr run one cmd: running on complete function")
onCompleteFunc(a, b)
}
case Failure(ex) =>
+ logger.debug("Running tlmgr command did no succeed" + ex.getMessage)
errorText += "Running a tlmgr command did not succeed: " + ex.getMessage
}
- // println(s"DEBUG sending ${s}")
+ logger.debug(s"sending to tlmgr: ${s}")
tlmgr.send_command(s)
}
@@ -1284,63 +1542,47 @@ object ApplicationMain extends JFXApp {
outputText.clear()
outerrpane.expanded = false
if (!currentPromise.isCompleted) {
- // println(s"DEBUG tlmgr busy, put onto pending jobs: $s")
+ logger.debug(s"tlmgr busy, put onto pending jobs: $s")
+ logger.debug("Currently running job: " + currentPromise)
pendingJobs += ((s, onCompleteFunc))
} else {
+ logger.debug(s"tlmgr_send sending ${s}")
tlmgr_run_one_cmd(s, onCompleteFunc)
}
}
def reinitialize_tlmgr(): Unit = {
+ logger.debug("reinit tlmgr: entering, clearing pending jobs")
+ pendingJobs.clear()
+ logger.debug("reinit tlmgr: cleared pending jobs")
+ // if (!currentPromise.isCompleted) {
+ // logger.debug("reinit tlmgr: current promise not complete, completing it")
+ // currentPromise.success(("",Array[String]()))
+ // logger.debug("reinit tlmgr: after completing current promise")
+ // }
+ logger.debug("reinit tlmgr: cleaning up tlmgr")
tlmgr.cleanup()
- // Thread.sleep(1000)
+ logger.debug("reinit tlmgr: sleeping 1s")
+ Thread.sleep(1000)
+ logger.debug("reinit tlmgr: initializaing new tlmgr")
tlmgr = initialize_tlmgr()
+ logger.debug("reinit tlmgr: finished")
tlmgr_post_init()
- pkgstabs.getSelectionModel().select(0)
+ logger.debug("reinit tlmgr: post init done")
+ updLoaded = false
+ pkgstabs.getSelectionModel.select(0)
}
- def tlmgr_post_init():Unit = {
- if (!tlmgr.start_process()) {
- println("Cannot start tlmgr process, terminating!")
- Platform.exit()
- sys.exit(1)
- }
-
- // check for tlmgr revision
- tlmgr_send("version", (status,output) => {
- output.foreach ( l => {
- if (l.startsWith("revision ")) {
- val tlmgrRev = l.stripPrefix("revision ")
- if (tlmgrRev == "unknown") {
- println("Unknown tlmgr revision, assuming git/svn version")
- logText += "Unknown tlmgr revision, assuming git/svn version"
- } else {
- if (tlmgrRev.toInt < 45838) {
- new Alert(AlertType.Error) {
- initOwner(stage)
- title = "TeX Live Manager tlmgr is too old"
- headerText = "TeX Live Manager tlmgr is too old"
- contentText = "Please update from the command line\nusing 'tlmgr update --self'\nTerminating!"
- }.showAndWait()
- callback_quit()
- }
- }
- }
- })
- pkgs.clear()
- upds.clear()
- bkps.clear()
- load_tlpdb_update_pkgs_view()
- })
- }
-
- def defaultStdoutLineUpdateFunc(l: String) : Unit = { } // println(s"DEBUG: got ==$l== from tlmgr") }
+ def defaultStdoutLineUpdateFunc(l: String) : Unit = { logger.trace(s"DEBUG: got ==$l== from tlmgr") }
def defaultStderrLineUpdateFunc(l: String) : Unit = { Platform.runLater { logText.append(l) } }
var stdoutLineUpdateFunc: String => Unit = defaultStdoutLineUpdateFunc
var stderrLineUpdateFunc: String => Unit = defaultStderrLineUpdateFunc
+
+
var tlmgr = initialize_tlmgr()
tlmgr_post_init()
+
} // object ApplicationMain
// vim:set tabstop=2 expandtab : //
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/LocationDialog.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/LocationDialog.scala
index 30088ff69a6..b762a811a05 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/LocationDialog.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/LocationDialog.scala
@@ -1,7 +1,14 @@
+// TLCockpit
+// Copyright 2017-2018 Norbert Preining
+// Licensed according to GPLv3+
+//
+// Front end for tlmgr
+
package TLCockpit
-import TLCockpit.ApplicationMain.{not_implemented_info, stage}
+import TLCockpit.ApplicationMain.stage
import TeXLive.{OsTools, TLOption}
+import com.typesafe.scalalogging.LazyLogging
import scalafx.Includes._
import scalafx.event.ActionEvent
@@ -10,7 +17,7 @@ import scalafx.scene.Node
import scalafx.scene.control._
import scalafx.scene.layout._
-class LocationDialog(locs: Map[String,String]) {
+class LocationDialog(locs: Map[String,String]) extends LazyLogging {
case class Result(selected: Map[String, String])
@@ -31,6 +38,8 @@ class LocationDialog(locs: Map[String,String]) {
var crow = 0
+ val mirrorlocs: Map[String, Map[String, Seq[String]]] = TLCockpit.ApplicationMain.parse_ctan_mirrors(TLCockpit.ApplicationMain.tlmgr.tlroot)
+
def do_one(tag: String, url: String): Unit = {
val tagNode = new TextField() {
text = tag
@@ -42,7 +51,21 @@ class LocationDialog(locs: Map[String,String]) {
grid.add(tagNode, 0, crow)
grid.add(urlNode, 1, crow)
newlocs += ((tagNode, urlNode))
- if (tag != "main") {
+ if (tag == "main") {
+ if (mirrorlocs.nonEmpty) {
+ grid.add(new MenuButton("Choose Mirror") {
+ items = mirrorlocs.toSeq.sortWith(_._1 < _._1)
+ .map(continent_pair => new Menu(continent_pair._1) {
+ items = continent_pair._2.toSeq.sortWith(_._1 < _._1)
+ .map(country_pair => new Menu(country_pair._1) {
+ items = country_pair._2.sortWith(_ < _).map(mirror => new MenuItem(mirror) {
+ onAction = (ae) => urlNode.text = mirror
+ })
+ })
+ })
+ }, 2, crow)
+ }
+ } else {
grid.add(new Button("Delete") {
onAction = _ => {
tagNode.disable = true
@@ -62,7 +85,7 @@ class LocationDialog(locs: Map[String,String]) {
val tagNode = new TextField()
val urlNode = new TextField()
newlocs += ((tagNode, urlNode))
- // println(s"current row = ${crow}")
+ logger.trace(s"current row = ${crow}")
grid.children.remove(addButton)
grid.add(tagNode, 0, crow)
grid.add(urlNode, 1, crow)
@@ -74,7 +97,7 @@ class LocationDialog(locs: Map[String,String]) {
}
}, 2, crow)
crow += 1
- // println(s"adding addButton at row ${crow}")
+ logger.trace(s"adding addButton at row ${crow}")
grid.add(addButton, 2, crow)
dialog.dialogPane.value.scene.value.window.value.sizeToScene()
}
@@ -104,10 +127,10 @@ class LocationDialog(locs: Map[String,String]) {
result match {
case Some(Result(foo)) =>
- // println("Got resutl " + foo)
+ logger.debug("Got result " + foo)
Some(foo)
case Some(foo) =>
- // println("Got strange result " + foo)
+ logger.debug("Got strange result " + foo)
None
case None =>
None
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/OptionsDialog.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/OptionsDialog.scala
index ca7228da7ee..497a5cb20de 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/OptionsDialog.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/OptionsDialog.scala
@@ -1,7 +1,14 @@
+// TLCockpit
+// Copyright 2017-2018 Norbert Preining
+// Licensed according to GPLv3+
+//
+// Front end for tlmgr
+
package TLCockpit
import TLCockpit.ApplicationMain.{not_implemented_info, stage}
import TeXLive.{OsTools, TLOption, TLPaperConf}
+import com.typesafe.scalalogging.LazyLogging
import scalafx.Includes._
import scalafx.collections.ObservableBuffer
@@ -11,7 +18,7 @@ import scalafx.scene.Node
import scalafx.scene.control._
import scalafx.scene.layout._
-class OptionsDialog(opts: List[TLOption]) {
+class OptionsDialog(opts: List[TLOption]) extends LazyLogging {
case class Result(selected: Map[String,String])
@@ -116,10 +123,10 @@ class OptionsDialog(opts: List[TLOption]) {
result match {
case Some(Result(foo)) =>
- // println("Got resutl " + foo)
+ logger.debug("Got result " + foo)
Some(foo)
case Some(foo) =>
- // println("Got strange result " + foo)
+ logger.debug("Got strange result " + foo)
None
case None =>
None
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/PaperDialog.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/PaperDialog.scala
index a195c23f654..0b4f7edf63f 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/PaperDialog.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/PaperDialog.scala
@@ -1,7 +1,14 @@
+// TLCockpit
+// Copyright 2017-2018 Norbert Preining
+// Licensed according to GPLv3+
+//
+// Front end for tlmgr
+
package TLCockpit
import TLCockpit.ApplicationMain.stage
import TeXLive.TLPaperConf
+import com.typesafe.scalalogging.LazyLogging
import scalafx.Includes._
import scalafx.collections.ObservableBuffer
@@ -9,7 +16,7 @@ import scalafx.geometry.{HPos, Insets}
import scalafx.scene.control._
import scalafx.scene.layout._
-class PaperDialog(paperconf: Map[String, TLPaperConf]) {
+class PaperDialog(paperconf: Map[String, TLPaperConf]) extends LazyLogging {
case class Result(selected: Map[String,String])
@@ -70,10 +77,10 @@ class PaperDialog(paperconf: Map[String, TLPaperConf]) {
result match {
case Some(Result(foo)) =>
- // println("Got resutl " + foo)
+ logger.debug("Got result " + foo)
Some(foo)
case Some(foo) =>
- // println("Got strange result " + foo)
+ logger.debug("Got strange result " + foo)
None
case None =>
None
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/PkgInfoDialog.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/PkgInfoDialog.scala
index 3b5ea6fc848..82585aa7591 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/PkgInfoDialog.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/PkgInfoDialog.scala
@@ -1,8 +1,14 @@
+// TLCockpit
+// Copyright 2017-2018 Norbert Preining
+// Licensed according to GPLv3+
+//
+// Front end for tlmgr
+
package TLCockpit
-import TLCockpit.ApplicationMain.{tlpkgs,tlmgr,stage}
+import TLCockpit.ApplicationMain.{stage, tlmgr, tlpkgs}
import TLCockpit.Utils._
-import TeXLive.OsTools
+import TeXLive.{OsTools, TLPackage}
import scalafx.Includes._
import scalafx.collections.ObservableBuffer
@@ -13,7 +19,7 @@ import scalafx.scene.control._
import scalafx.scene.input.MouseEvent
import scalafx.scene.paint.Color
-class PkgInfoDialog(pkg: String) extends Dialog {
+class PkgInfoDialog(tlp: TLPackage) extends Dialog {
val dialog = new Dialog() {
initOwner(stage)
title = s"Package Information for $pkg"
@@ -21,7 +27,7 @@ class PkgInfoDialog(pkg: String) extends Dialog {
resizable = true
}
dialog.dialogPane().buttonTypes = Seq(ButtonType.OK)
- val isInstalled = tlpkgs(pkg).installed
+ val isInstalled = tlp.installed
val grid = new GridPane() {
hgap = 10
vgap = 10
@@ -37,7 +43,7 @@ class PkgInfoDialog(pkg: String) extends Dialog {
}
var crow = 0
- val tlp = tlpkgs(pkg)
+ val pkg = tlp.name
crow = do_one("package", pkg, crow)
crow = do_one("category", tlp.category, crow)
crow = do_one("shortdesc", tlp.shortdesc.getOrElse(""), crow)
@@ -48,44 +54,44 @@ class PkgInfoDialog(pkg: String) extends Dialog {
crow = do_one("local revision", tlp.lrev.toString, crow)
if (tlp.available)
crow = do_one("remote revision", tlp.rrev.toString, crow)
- val binsizesum = tlp.binsize.map { _._2}.toList.foldLeft[Long](0)(_ + _) * TeXLive.tlBlockSize
- val binsizestr = if (binsizesum > 0) "bin " + humanReadableByteSize(binsizesum) + " " else "";
- val runsizestr = if (tlp.runsize > 0) "run " + humanReadableByteSize(tlp.runsize) + " " else "";
- val srcsizestr = if (tlp.srcsize > 0) "src " + humanReadableByteSize(tlp.srcsize) + " " else "";
- val docsizestr = if (tlp.docsize > 0) "doc " + humanReadableByteSize(tlp.docsize) + " " else "";
+ val binsizesum = tlp.binsize.values.toList.sum * TeXLive.tlBlockSize
+ val binsizestr = if (binsizesum > 0) "bin " + humanReadableByteSize(binsizesum) + " " else ""
+ val runsizestr = if (tlp.runsize > 0) "run " + humanReadableByteSize(tlp.runsize) + " " else ""
+ val srcsizestr = if (tlp.srcsize > 0) "src " + humanReadableByteSize(tlp.srcsize) + " " else ""
+ val docsizestr = if (tlp.docsize > 0) "doc " + humanReadableByteSize(tlp.docsize) + " " else ""
crow = do_one("sizes", runsizestr + docsizestr + binsizestr + srcsizestr, crow)
val catdata = tlp.cataloguedata
- if (catdata.version != None)
+ if (catdata.version.isDefined)
crow = do_one("cat-version", catdata.version.get, crow)
- if (catdata.date != None)
+ if (catdata.date.isDefined)
crow = do_one("cat-date", catdata.date.get, crow)
- if (catdata.license != None)
+ if (catdata.license.isDefined)
crow = do_one("cat-license", catdata.license.get, crow)
- if (catdata.topics != None)
+ if (catdata.topics.isDefined)
crow = do_one("cat-topics", catdata.topics.get, crow)
- if (catdata.related != None)
+ if (catdata.related.isDefined)
crow = do_one("cat-related", catdata.related.get, crow)
// add files section
//println(tlpkgs(pkg))
- val docFiles = tlpkgs(pkg).docfiles
+ val docFiles = tlp.docfiles
if (docFiles.nonEmpty) {
grid.add(new Label("doc files"), 0, crow)
grid.add(doListView(docFiles.map(s => s.file.replaceFirst("RELOC", "texmf-dist")), isInstalled), 1, crow)
crow += 1
}
- val runFiles = tlpkgs(pkg).runfiles
+ val runFiles = tlp.runfiles
if (runFiles.nonEmpty) {
grid.add(new Label("run files"), 0, crow)
grid.add(doListView(runFiles.map(s => s.replaceFirst("RELOC", "texmf-dist")), false), 1, crow)
crow += 1
}
- val srcFiles = tlpkgs(pkg).srcfiles
+ val srcFiles = tlp.srcfiles
if (srcFiles.nonEmpty) {
grid.add(new Label("src files"), 0, crow)
grid.add(doListView(srcFiles.map(s => s.replaceFirst("RELOC", "texmf-dist")), false), 1, crow)
crow += 1
}
- val binFiles = tlpkgs(pkg).binfiles
+ val binFiles = tlp.binfiles
if (binFiles.nonEmpty) {
grid.add(new Label("bin files"), 0, crow)
grid.add(doListView(binFiles.flatMap(_._2).toSeq.map(s => s.replaceFirst("RELOC", "texmf-dist")), false), 1, crow)
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/TLDisplayClasses.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/TLDisplayClasses.scala
index 630cbfce061..b49c13c1624 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/TLDisplayClasses.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/TLDisplayClasses.scala
@@ -1,3 +1,9 @@
+// TLCockpit
+// Copyright 2017-2018 Norbert Preining
+// Licensed according to GPLv3+
+//
+// Front end for tlmgr
+
package TLCockpit
import scalafx.beans.property.{ObjectProperty, StringProperty}
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/Utils.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/Utils.scala
index fb364f12f80..aae40d5db37 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/Utils.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TLCockpit/Utils.scala
@@ -1,3 +1,9 @@
+// TLCockpit
+// Copyright 2017-2018 Norbert Preining
+// Licensed according to GPLv3+
+//
+// Front end for tlmgr
+
package TLCockpit
object Utils {
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/JsonProtocol.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/JsonProtocol.scala
index 3e28c582f2a..2302d308bdd 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/JsonProtocol.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/JsonProtocol.scala
@@ -1,3 +1,9 @@
+// TLCockpit
+// Copyright 2017-2018 Norbert Preining
+// Licensed according to GPLv3+
+//
+// Front end for tlmgr
+
package TeXLive
import spray.json._
@@ -6,6 +12,7 @@ import spray.json._
object JsonProtocol extends DefaultJsonProtocol {
implicit val catalogueDataFormat = jsonFormat6(CatalogueData)
implicit val docfileFormat = jsonFormat3(DocFile)
+ implicit val tlpackageshortFormat = jsonFormat8(TLPackageShort)
implicit val tlpackageFormat = jsonFormat19(TLPackage)
implicit val tlbackupFormat = jsonFormat3(TLBackup)
implicit val tlpaperconfFormat = jsonFormat3(TLPaperConf)
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsTools.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsTools.scala
index 4590eb6b5c5..45a50ae884c 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsTools.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/OsTools.scala
@@ -1,4 +1,9 @@
package TeXLive
+// TLCockpit
+// Copyright 2017-2018 Norbert Preining
+// Licensed according to GPLv3+
+//
+// Front end for tlmgr
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLClasses.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLClasses.scala
index c526ae50739..e647ef726eb 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLClasses.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TLClasses.scala
@@ -1,3 +1,9 @@
+// TLCockpit
+// Copyright 2017-2018 Norbert Preining
+// Licensed according to GPLv3+
+//
+// Front end for tlmgr
+
package TeXLive
// classes that wrap up structures in TeX Live
@@ -10,6 +16,18 @@ case class DocFile(file: String, details: Option[String], language: Option[Strin
case class TLPaperConf(program: String, file: String, options: List[String])
case class TLBackup(name: String, rev: String, date: String)
+case class TLPackageShort
+(
+ name: String,
+ shortdesc: Option[String],
+ var lrev: Long,
+ rrev: Long,
+ category: String,
+ depends: List[String],
+ var installed: Boolean,
+ available: Boolean
+)
+
case class TLPackage
(
name: String,
@@ -54,3 +72,4 @@ case class TLOptions
file_assocs: Option[Long]
)
+
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala
index 7d84e6dd008..5776daef76d 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/TlmgrProcess.scala
@@ -1,31 +1,39 @@
+// TLCockpit
+// Copyright 2017-2018 Norbert Preining
+// Licensed according to GPLv3+
+//
+// Front end for tlmgr
+
package TeXLive
import java.io._
import TeXLive.OsTools._
+import com.typesafe.scalalogging.LazyLogging
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.SyncVar
import scala.sys.process._
-class TlmgrProcess(updout: String => Unit, upderr: String => Unit) {
+class TlmgrProcess(updout: String => Unit, upderr: String => Unit) extends LazyLogging {
val inputString = new SyncVar[String] // used for the tlmgr process input
// val outputString = new SyncVar[String] // used for the tlmgr process output
// val errorBuffer: StringBuffer = new StringBuffer() // buffer used for both tmgr process error console AND logging
- val tlroot = "kpsewhich -var-value SELFAUTOPARENT".!!.trim
- // println("tlroot ==" + tlroot + "==")
+ val tlroot: String = "kpsewhich -var-value SELFAUTOPARENT".!!.trim
+ logger.debug("tlroot ==" + tlroot + "==")
// set in only one place, in the main thread
var process: Process = _
def send_command(input: String): Unit = {
+ logger.debug(s"send_command: ${input}")
try {
assert(!inputString.isSet)
inputString.put(input)
} catch {
case exc: Throwable =>
- upderr("Main thread: " +
+ logger.warn("Main thread: " +
(if (exc.isInstanceOf[NoSuchElementException]) "Timeout" else "Exception: " + exc))
}
}
@@ -39,18 +47,26 @@ class TlmgrProcess(updout: String => Unit, upderr: String => Unit) {
}
def start_process(): Boolean = {
+ logger.debug("tlmgr process: entering starting process")
// process creation
if (process == null) {
- val procIO = new ProcessIO(inputFn(_), outputFn(_, updout), outputFn(_, upderr))
+ logger.debug("tlmgr process: start_process: creating procIO")
+ val procIO = new ProcessIO(inputFn, outputFn(_, updout), outputFn(_, upderr))
val processBuilder: ProcessBuilder = Seq({if (isWindows) "tlmgr.bat" else "tlmgr"}, "-v", "--machine-readable", "shell")
+ logger.debug("tlmgr process: start_process: running new tlmgr process")
process = processBuilder.run(procIO)
}
+ logger.debug("tlmgr process: start_process: checking for being alive")
process.isAlive()
}
def cleanup(): Unit = {
if (process != null) {
+ logger.debug("tlmgr process: cleanup - sending quit")
send_command("quit")
+ logger.debug("tlmgr process: cleanup - sleeping 2s")
+ Thread.sleep(1000)
+ logger.debug("tlmgr process: cleanup - destroying process")
process.destroy()
}
}
@@ -67,7 +83,7 @@ class TlmgrProcess(updout: String => Unit, upderr: String => Unit) {
return
} else {
writer.write(input + "\n")
- // println("writing " + input + " to process")
+ logger.trace("writing " + input + " to process")
writer.flush()
}
}
@@ -75,8 +91,7 @@ class TlmgrProcess(updout: String => Unit, upderr: String => Unit) {
} catch {
case exc: Throwable =>
stdin.close()
- // println("Exception in inputFn thread: " + exc + "\n")
- upderr("Input thread: Exception: " + exc + "\n")
+ logger.warn("Exception in inputFn thread: " + exc + "\n")
}
}
@@ -86,19 +101,19 @@ class TlmgrProcess(updout: String => Unit, upderr: String => Unit) {
var line: String = ""
while (true) {
line = reader.readLine
- // println("DDD did read " + line + " from process")
+ logger.trace("DDD did read " + line + " from process")
try {
updfun(line)
} catch {
case exc: Throwable =>
- upderr("Update output line function failed, continuing anyway. Exception: " + exc)
+ logger.debug("Update output line function failed, continuing anyway. Exception: " + exc)
}
}
outStr.close()
} catch {
case exc: Throwable =>
outStr.close()
- upderr("Output thread: Exception: " + exc + "\n")
+ logger.warn("Exception in outputFn thread: " + exc + "\n")
}
}
}
diff --git a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/package.scala b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/package.scala
index 88b3bb3e41a..074a7a86153 100644
--- a/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/package.scala
+++ b/Master/texmf-dist/source/support/tlcockpit/src/main/scala/TeXLive/package.scala
@@ -1,3 +1,8 @@
+// TLCockpit
+// Copyright 2017-2018 Norbert Preining
+// Licensed according to GPLv3+
+//
+// Front end for tlmgr
package object TeXLive {
val tlBlockSize = 4096 // TL gives sizes in multiples of BlockSize!