[education/rkward/releases/0.8.0] rkward/rbackend/rpackages/rkward: added new function rk.download_appimage()

Thomas Friedrichsmeier null at kde.org
Thu Jul 18 19:59:06 BST 2024


Git commit 695595f6a418e5ac007227759bfa3ba437a0d838 by Thomas Friedrichsmeier, on behalf of m.eik michalke.
Committed on 18/07/2024 at 18:58.
Pushed by tfry into branch 'releases/0.8.0'.

added new function rk.download_appimage()

M  +7    -11   rkward/rbackend/rpackages/rkward/DESCRIPTION
M  +1    -0    rkward/rbackend/rpackages/rkward/NAMESPACE
A  +148  -0    rkward/rbackend/rpackages/rkward/R/rk.download_appimage.R
M  +1    -1    rkward/rbackend/rpackages/rkward/R/rkward-package.R
A  +71   -0    rkward/rbackend/rpackages/rkward/man/rk.download_appimage.Rd
M  +1    -1    rkward/rbackend/rpackages/rkward/man/rkward-package.Rd

https://invent.kde.org/education/rkward/-/commit/695595f6a418e5ac007227759bfa3ba437a0d838

diff --git a/rkward/rbackend/rpackages/rkward/DESCRIPTION b/rkward/rbackend/rpackages/rkward/DESCRIPTION
index 98661b373..e6009ba04 100755
--- a/rkward/rbackend/rpackages/rkward/DESCRIPTION
+++ b/rkward/rbackend/rpackages/rkward/DESCRIPTION
@@ -1,12 +1,9 @@
 Package: rkward
 Type: Package
 Title: Provides functions related to the RKWard GUI
-Description: This package contains functions which are useful in
-        combination with the RKWard GUI. Many of these functions are
-        only needed for the internal communication between RKWard and
-        R, but some are also useful in user scripts.
-Author: Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net> and
-        the RKWard Team <rkward-devel at kde.org>
+Description: This package contains functions which are useful in combination with the RKWard GUI. Many of these functions are only needed for the internal communication between
+                    RKWard and R, but some are also useful in user scripts.
+Author: Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net> and the RKWard Team <rkward-devel at kde.org>
 Maintainer: RKWard-devel mailing list <rkward-devel at kde.org>
 Depends: R (>= 2.9.0),methods
 Suggests: Cairo,googleVis,htmlwidgets,lattice,R2HTML
@@ -15,12 +12,10 @@ BugReports: https://rkward.kde.org/Bugs.html
 License: GPL (>= 2)
 Encoding: UTF-8
 LazyLoad: yes
-Authors at R: c(person(given="Thomas", family="Friedrichsmeier",
-        email="thomas.friedrichsmeier at kdemail.net", role=c("aut")),
-        person(given="the RKWard", family="team",
-        email="rkward-devel at kde.org", role=c("cre","aut")))
+Authors at R: c(person(given="Thomas", family="Friedrichsmeier", email="thomas.friedrichsmeier at kdemail.net", role=c("aut")), person(given="the RKWard", family="team",
+                    email="rkward-devel at kde.org", role=c("cre","aut")))
 Version: 0.8.0
-Date: 2024-07-15
+Date: 2024-07-18
 RoxygenNote: 7.3.1
 Collate: 
     'base_overrides.R'
@@ -33,6 +28,7 @@ Collate:
     'rk.check.for.pandoc.R'
     'rk.completion-functions.R'
     'rk.demo.R'
+    'rk.download_appimage.R'
     'rk.edit-functions.R'
     'rk.filename-functions.R'
     'rk.label-functions.R'
diff --git a/rkward/rbackend/rpackages/rkward/NAMESPACE b/rkward/rbackend/rpackages/rkward/NAMESPACE
index 96e3063a7..de67aaafc 100644
--- a/rkward/rbackend/rpackages/rkward/NAMESPACE
+++ b/rkward/rbackend/rpackages/rkward/NAMESPACE
@@ -55,6 +55,7 @@ export(rk.clear.plot.history)
 export(rk.demo)
 export(rk.describe.alternative)
 export(rk.discard.preview.data)
+export(rk.download_appimage)
 export(rk.duplicate.device)
 export(rk.edit)
 export(rk.edit.files)
diff --git a/rkward/rbackend/rpackages/rkward/R/rk.download_appimage.R b/rkward/rbackend/rpackages/rkward/R/rk.download_appimage.R
new file mode 100644
index 000000000..5310025ea
--- /dev/null
+++ b/rkward/rbackend/rpackages/rkward/R/rk.download_appimage.R
@@ -0,0 +1,148 @@
+# - This file is part of the RKWard project (https://rkward.kde.org).
+# SPDX-FileCopyrightText: by Thomas Friedrichsmeier <thomas.friedrichsmeier at kdemail.net>
+# SPDX-FileContributor: The RKWard Team <rkward-devel at kde.org>
+# SPDX-License-Identifier: GPL-2.0-or-later
+#' Install or update RKWard AppImage file
+#'
+#' Tries to download the latest AppImage of RKWard to a specified directory and
+#' makes it executable so it can be used for launching RKWard.
+#' 
+#' This function uses functions of the \code{XiMpLe} package, allthough for technical
+#' reasons that package could not be declared a proper dependency. This means, if
+#' you use this function for the first time with the current R version and hadn't
+#' installed \code{XiMpLe} yet, you will be prompted to install it first. This
+#' behaviour is similar to using an RKWard plugin dialog with a \code{require()}
+#' call to a currently not installed package.
+#'
+#' @param dir File path to the target directory.
+#' @param filename Character string, filename for the downloaded AppImage.
+#' @param download Logical, whether to actually download the file or only return the full URL to it in a character string.
+#' @param overwrite Logical, should an existing file be overwritten?
+#' @param url Base URL to download the AppImage from.
+#' @param pattern Regular expression to find the AppImage file name in \code{url}.
+#' @param method See \code{\link[utils:download.file]{download.file}}.
+#' @param cacheOK See \code{\link[utils:download.file]{download.file}}.
+#' @param timeout Number of seconds to try finishing the download.
+#' @param ... Additionsl options for \code{\link[utils:download.file]{download.file}}.
+#' @return If \code{download = FALSE} returns the direct URL to the AppImage file.
+#'    Otherwise returns the invisible file path to the installed AppImage if all went well,
+#'    or invisible \code{NULL} if something went wrong.
+#' @author Meik Michalke \email{rkward-devel@@kde.org}
+#' @keywords utilities misc
+# # don't create additional dependencies for the rkward package
+# @importFrom XiMpLe parseXMLTree XMLScanDeep
+# @importFrom utils download.file
+#' @rdname rk.download_appimage
+#' @export
+#' @examples
+#' \dontrun{
+#' # install current AppImage from master branch to ~/bin
+#' rk.download_appimage(dir="~/bin")
+#'
+#' # update the AppImage
+#' rk.download_appimage(dir="~/bin", overwrite=TRUE)
+#' }
+
+rk.download_appimage <- function(
+    dir = dirname(Sys.getenv("APPIMAGE"))
+  , filename = "rkward-master-linux-gcc-x86_64.AppImage"
+  , download = TRUE
+  , overwrite = FALSE
+  , url = "https://cdn.kde.org/ci-builds/education/rkward/master/linux"
+  , pattern = "rkward-master.*linux-gcc-x86_64\\.AppImage"
+  , method = "auto"
+  , cacheOK = FALSE
+  , timeout =  max(400, getOption("timeout"))
+  , ...
+){
+
+  # we are well aware that require() is not the method of choice
+  # this call will invoke rkward::require(), which should only be present
+  # in a running session of RKWard, and therefore ask for the installation
+  # of XiMpLe if the package is currently missing in the R version that
+  # is running at the moment
+  rkward::require(XiMpLe)
+  XiMpLe_version <- utils::packageVersion("XiMpLe")
+  if(isFALSE(XiMpLe_version >= "0.11.3")){
+    stop(simpleError(paste0("rk.download_appimage() requires XiMpLe >= 0.11.3, but only found ", XiMpLe_version, ". Please update XiMpLe.")))
+  } else {}
+  rk_ai_html <- XiMpLe::parseXMLTree(url, drop="empty_attributes")
+  rk_ai_hrefs <- XiMpLe::XMLScanDeep(rk_ai_html, find="href")
+  rk_ai_file <- rk_ai_hrefs[grepl(pattern=pattern, x=rk_ai_hrefs)][[1]]
+
+  rk_ai_full_url <- file.path(url, rk_ai_file)
+
+  if(isTRUE(download)){
+    if(!dir.exists(dir)){
+      stop(simpleError(paste0("Target directory does not exist:\n  ", dir)))
+    } else {}
+    have_backup <- FALSE
+    target_file <- file.path(dir, filename)
+    if(file.exists(target_file)){
+      if(isFALSE(overwrite)){
+        stop(simpleError(paste0("Target file already exists, use the \"overwrite\" argument to replace it:\n  ", target_file)))
+      } else {}
+      # create backup of current AppImage as a fallback
+      rk_ai_backup <- paste0(target_file, ".backup_", format(Sys.time(), "%Y-%m-%d_%H%M%S"))
+      message(paste0("Creating backup of current AppImage:\n  ", rk_ai_backup))
+      file.rename(
+          from=target_file
+        , to=rk_ai_backup
+      )
+      have_backup <- TRUE
+    } else {}
+    timeout_orig <- getOption("timeout")
+    options(timeout = timeout)
+    dl_status <- tryCatch(
+        # value should be 0 if download was successful
+        utils::download.file(
+            url = rk_ai_full_url
+          , destfile = target_file
+          , method = method
+          , cacheOK = cacheOK
+          , quiet = FALSE
+          , ...
+        )
+      , error = function(cond){
+          if(isTRUE(have_backup)){
+            file.rename(
+                from=rk_ai_backup
+              , to=target_file
+            )
+            stop("Something went wrong with the download! Restored previous AppImage from backup.", call.=FALSE)
+          } else {
+            file.remove(target_file)
+            stop("Something went wrong with the download!", call.=FALSE)
+          }
+        }
+      , finally = options(timeout = timeout_orig)
+    )
+    if(isTRUE(dl_status == 0)){
+      message("Download successful, setting file permissions.")
+      Sys.chmod(
+          paths=target_file
+        , mode="0755"
+        , use_umask=TRUE
+      )
+      if(isTRUE(have_backup)){
+        message("Removing backup of previous AppImage.")
+        file.remove(rk_ai_backup)
+      } else {}
+      return(invisible(target_file))
+    } else {
+      if(isTRUE(have_backup)){
+        warning("Something went wrong with the download! Restoring previous AppImage from backup.", call.=FALSE)
+        file.rename(
+            from=rk_ai_backup
+          , to=target_file
+        )
+      } else {
+        warning("Something went wrong with the download!", call.=FALSE)
+        file.remove(target_file)
+      }
+    }
+    return(invisible(NULL))
+  } else {
+    return(rk_ai_full_url)
+  }
+}
diff --git a/rkward/rbackend/rpackages/rkward/R/rkward-package.R b/rkward/rbackend/rpackages/rkward/R/rkward-package.R
index e0103a470..5f63c8896 100644
--- a/rkward/rbackend/rpackages/rkward/R/rkward-package.R
+++ b/rkward/rbackend/rpackages/rkward/R/rkward-package.R
@@ -13,7 +13,7 @@
 #' Package: \tab rkward\cr
 #' Type: \tab Package\cr
 #' Version: \tab 0.8.0\cr
-#' Date: \tab 2024-07-11\cr
+#' Date: \tab 2024-07-18\cr
 #' Depends: \tab R (>= 2.9.0),methods\cr
 #' Encoding: \tab UTF-8\cr
 #' License: \tab GPL (>= 2)\cr
diff --git a/rkward/rbackend/rpackages/rkward/man/rk.download_appimage.Rd b/rkward/rbackend/rpackages/rkward/man/rk.download_appimage.Rd
new file mode 100644
index 000000000..9f9295a84
--- /dev/null
+++ b/rkward/rbackend/rpackages/rkward/man/rk.download_appimage.Rd
@@ -0,0 +1,71 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/rk.download_appimage.R
+\name{rk.download_appimage}
+\alias{rk.download_appimage}
+\title{Install or update RKWard AppImage file}
+\usage{
+rk.download_appimage(
+  dir = dirname(Sys.getenv("APPIMAGE")),
+  filename = "rkward-master-linux-gcc-x86_64.AppImage",
+  download = TRUE,
+  overwrite = FALSE,
+  url = "https://cdn.kde.org/ci-builds/education/rkward/master/linux",
+  pattern = "rkward-master.*linux-gcc-x86_64\\\\.AppImage",
+  method = "auto",
+  cacheOK = FALSE,
+  timeout = max(400, getOption("timeout")),
+  ...
+)
+}
+\arguments{
+\item{dir}{File path to the target directory.}
+
+\item{filename}{Character string, filename for the downloaded AppImage.}
+
+\item{download}{Logical, whether to actually download the file or only return the full URL to it in a character string.}
+
+\item{overwrite}{Logical, should an existing file be overwritten?}
+
+\item{url}{Base URL to download the AppImage from.}
+
+\item{pattern}{Regular expression to find the AppImage file name in \code{url}.}
+
+\item{method}{See \code{\link[utils:download.file]{download.file}}.}
+
+\item{cacheOK}{See \code{\link[utils:download.file]{download.file}}.}
+
+\item{timeout}{Number of seconds to try finishing the download.}
+
+\item{...}{Additionsl options for \code{\link[utils:download.file]{download.file}}.}
+}
+\value{
+If \code{download = FALSE} returns the direct URL to the AppImage file.
+   Otherwise returns the invisible file path to the installed AppImage if all went well,
+   or invisible \code{NULL} if something went wrong.
+}
+\description{
+Tries to download the latest AppImage of RKWard to a specified directory and
+makes it executable so it can be used for launching RKWard.
+}
+\details{
+This function uses functions of the \code{XiMpLe} package, allthough for technical
+reasons that package could not be declared a proper dependency. This means, if
+you use this function for the first time with the current R version and hadn't
+installed \code{XiMpLe} yet, you will be prompted to install it first. This
+behaviour is similar to using an RKWard plugin dialog with a \code{require()}
+call to a currently not installed package.
+}
+\examples{
+\dontrun{
+# install current AppImage from master branch to ~/bin
+rk.download_appimage(dir="~/bin")
+
+# update the AppImage
+rk.download_appimage(dir="~/bin", overwrite=TRUE)
+}
+}
+\author{
+Meik Michalke \email{rkward-devel at kde.org}
+}
+\keyword{misc}
+\keyword{utilities}
diff --git a/rkward/rbackend/rpackages/rkward/man/rkward-package.Rd b/rkward/rbackend/rpackages/rkward/man/rkward-package.Rd
index 32ce866f9..1ac26d448 100644
--- a/rkward/rbackend/rpackages/rkward/man/rkward-package.Rd
+++ b/rkward/rbackend/rpackages/rkward/man/rkward-package.Rd
@@ -14,7 +14,7 @@ The DESCRIPTION file:
 Package: \tab rkward\cr
 Type: \tab Package\cr
 Version: \tab 0.8.0\cr
-Date: \tab 2024-07-11\cr
+Date: \tab 2024-07-18\cr
 Depends: \tab R (>= 2.9.0),methods\cr
 Encoding: \tab UTF-8\cr
 License: \tab GPL (>= 2)\cr


More information about the rkward-tracker mailing list