~hrbrmstr/vershist

3ed9508453c2be38c98a0b8b90a4c35e9f187307 — boB Rudis 4 years ago 7c4c4ac
iOS and more utility functions
M NAMESPACE => NAMESPACE +4 -1
@@ 1,8 1,10 @@
# Generated by roxygen2: do not edit by hand

export(apache_httpd_version_history)
export(apple_ios_version_history)
export(complete_semver)
export(google_chrome_version_history)
export(is_valid)
export(is_valid_semver)
export(lighttpd_version_history)
export(memcached_version_history)
export(mongodb_version_history)


@@ 50,6 52,7 @@ importFrom(rvest,xml_nodes)
importFrom(stringi,stri_count_fixed)
importFrom(stringi,stri_detect_fixed)
importFrom(stringi,stri_detect_regex)
importFrom(stringi,stri_extract_all_regex)
importFrom(stringi,stri_extract_first_regex)
importFrom(stringi,stri_match_first_regex)
importFrom(stringi,stri_replace_all_fixed)

M NEWS.md => NEWS.md +2 -2
@@ 1,4 1,4 @@
0.1.0 
* Initial release
* Support for Apache httpd, Google Chrome lighttpd, memcached, mongodb, nginx, mysql,
  openresty, openssh, sendmail and sqlite
\ No newline at end of file
* Support for Apache httpd, Apple iOS, Google Chrome lighttpd, memcached, mongodb, nginx, 
  mysql, openresty, openssh, sendmail and sqlite
\ No newline at end of file

M R/RcppExports.R => R/RcppExports.R +3 -3
@@ 1,11 1,11 @@
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

#' Test if semantic version strings are valid
#' Test if semantic version strings are valid tri-string
#'
#' @param v character verctor of version strings
#' @export
is_valid <- function(v) {
    .Call('_vershist_is_valid', PACKAGE = 'vershist', v)
is_valid_semver <- function(v) {
    .Call('_vershist_is_valid_semver', PACKAGE = 'vershist', v)
}


A R/ios.R => R/ios.R +62 -0
@@ 0,0 1,62 @@
#' Retrieve Apple iOS  Version Release History
#'
#' Reads <https://en.wikipedia.org/wiki/IOS_version_history"> to build a data
#' frame of Apple iOS version release numbers and dates with pseudo-semantic version
#' strings parsed and separate fields added. The data frame is also arranged in
#' order from lowest version to latest version and the `vers` column is an
#' ordered factor.
#'
#' @md
#' @note This does not distinguish by device target and only pulls the first release
#'       date and excludes betas. If more granular data is needed, file an issue or PR.
#' @export
apple_ios_version_history <- function() {

  pg <- xml2::read_html("https://en.wikipedia.org/wiki/IOS_version_history")

  vers_nodes <- rvest::html_nodes(pg, xpath=".//th[contains(@id, '.') or contains(., '.')]")

  dplyr::data_frame(
    vers = rvest::html_text(vers_nodes),
    rls_date = purrr::map_chr(
      vers_nodes,
      ~rvest::html_node(.x, xpath=".//following-sibling::td[3]") %>%
        rvest::html_text()
    )
  ) %>%
    dplyr::filter(!stri_detect_regex(vers, "Table|Post|Apple")) %>%
    dplyr::mutate(vers = stri_replace_all_regex(vers, "\\[.*\\]", "")) -> xdf

  dplyr::filter(xdf, !stri_detect_fixed(vers, "/")) %>%
    dplyr::mutate(
      rls_date = stri_extract_first_regex(
        rls_date, "[[:alpha:]]{2,}[[:space:]]+[[:digit:]]{1,2},[[:space:]]+[[:digit:]]{4}"
      )
    ) -> simple

  more_complex <- dplyr::filter(xdf, stri_detect_fixed(vers, "/"))

  c_v <- stri_extract_all_regex(more_complex$vers, "[[:digit:]\\.]+")
  c_d <- stri_extract_all_regex(more_complex$rls_date, "[[:alpha:]]{2,}[[:space:]]+[[:digit:]]{1,2},[[:space:]]+[[:digit:]]{4}")

  purrr::map2_df(c_v, c_d, ~{
    dplyr::data_frame(
      vers = .x,
      rls_date = .y
    )
  }) -> more_complex

  dplyr::bind_rows(simple, more_complex) %>%
    dplyr::mutate(rls_date = lubridate::mdy(rls_date)) %>%
    dplyr::filter(!stri_detect_fixed(vers, "Beta")) %>%
    dplyr::mutate(
      vers = ifelse(stri_count_fixed(vers, ".") == 1, sprintf("%s.0", vers), vers)
    ) %>%
    dplyr::bind_cols(
      semver::parse_version(.$vers) %>%
        dplyr::as_data_frame()
    ) %>%
    dplyr::arrange(major, minor, patch) %>%
    dplyr::mutate(vers = factor(vers, levels = vers))

}
\ No newline at end of file

M R/lighttpd.R => R/lighttpd.R +1 -1
@@ 3,7 3,7 @@
#' Reads from the `lighttpd` releases and snapshot downloads to build a
#' data frame of version release numbers and dates. The caller is responsible
#' for extracting out the version components due to the non-standard
#' semantic versioning used. The [is_valid()] function can be used to test the
#' semantic versioning used. The [is_valid_semver()] function can be used to test the
#' validity of version strings.
#'
#' @md

A R/utils.R => R/utils.R +34 -0
@@ 0,0 1,34 @@
#' Turn partial "valid" semantic version strings into a complete semver-tri or quad strings
#'
#' For MAJOR.MINOR.PATCH (semver-tri), turn `1` into `1.0.0`; `1.1` into `1.1.0`; `1.1.1`
#' into `1.1.1`. For MAJOR.MINOR.PATCH.EXTENSION (semver-quad), turn `1` into `1.0.0.0`;
#' `1.1` into `1.1.0.0`; `1.1.1.0` into `1.1.1.0`.
#'
#' Partial validity checking is performed to test if the input strings contain only
#' digits and periods. "Invalid" input is returned unscathed.
#'
#' @param x a character vector of full or partial version strings
#' @param quad (logical) if `TRUE` then a three-dot semver is returned, else a two-dot semver
#'        is returned. Default: `FALSE`.
#' @export
complete_semver <- function(x, quad = FALSE) {

  x <- stri_trim_both(x)
  x <- stri_replace_all_regex(x, "(^\\.|\\.$)", "")

  max_dots <- if (quad) 3 else 2

  purrr::map_chr(x, ~{
    if (stri_detect_regex(.x, "^[[:digit:]\\.]+$")) {
      times <- max_dots - stri_count_fixed(.x, ".")
      if (times > 0) {
        sprintf("%s%s", .x, paste0(rep(".0", times), collapse=""))
      } else {
        .x
      }
    } else {
      .x
    }
  })

}

M R/vershist-package.R => R/vershist-package.R +1 -0
@@ 15,6 15,7 @@
#' @importFrom stringi stri_replace_all_regex stri_replace_first_fixed stri_trans_tolower
#' @importFrom stringi stri_extract_first_regex stri_sub stri_replace_first_regex
#' @importFrom stringi stri_replace_all_fixed stri_split_fixed stri_count_fixed stri_trim_both
#' @importFrom stringi stri_extract_all_regex
#' @importFrom lubridate year mdy mdy_hms parse_date_time
#' @importFrom readr read_lines
#' @importFrom utils globalVariables

M README.Rmd => README.Rmd +24 -1
@@ 1,5 1,7 @@
---
output: rmarkdown::github_document
editor_options: 
  chunk_output_type: console
---

# vershist


@@ 18,6 20,7 @@ The following functions are implemented:
Core:

- `apache_httpd_version_history`:	Retrieve Apache httpd Version Release History
- `apple_ios_version_history`:	Retrieve Apple iOS Version Release History
- `google_chrome_version_history`:	Retrieve Google Chrome Version Release History
- `lighttpd_version_history`:	Retrieve lighttpd Version Release History
- `memcached_version_history`:	Retrieve memcached Version Release History


@@ 31,7 34,8 @@ Core:

Utility:

- `is_valid`:	Test if semantic version strings are valid
- `is_valid_semver`:	Test if semantic version strings are valid
- `complete_semver`:	Turn partial "valid" semantic version strings into a complete semver-tri or quad strings

## Installation



@@ 52,12 56,31 @@ library(vershist)
packageVersion("vershist")
```

Utility

```{r utility}
versions <- c("steve", "1", "2.1", "3.2.1", "4.3.2.1")

# Technically, a "valid" semver string is MAJOR.MINOR.PATCH
is_valid_semver(versions)

complete_semver(versions)

complete_semver(versions, quad=TRUE)
```

Apache

```{r apache, cache=TRUE}
apache_httpd_version_history()
```

Apple iOS

```{r apple_ios, cache=TRUE}
apple_ios_version_history()
```

Google Chrome

```{r chrome, cache=TRUE}

M README.md => README.md +49 -1
@@ 16,6 16,8 @@ Core:

  - `apache_httpd_version_history`: Retrieve Apache httpd Version
    Release History
  - `apple_ios_version_history`: Retrieve Apple iOS Version Release
    History
  - `google_chrome_version_history`: Retrieve Google Chrome Version
    Release History
  - `lighttpd_version_history`: Retrieve lighttpd Version Release


@@ 34,7 36,9 @@ Core:

Utility:

  - `is_valid`: Test if semantic version strings are valid
  - `is_valid_semver`: Test if semantic version strings are valid
  - `complete_semver`: Turn partial “valid” semantic version strings
    into a complete semver-tri or quad strings

## Installation



@@ 53,6 57,29 @@ packageVersion("vershist")

    ## [1] '0.1.0'

Utility

``` r
versions <- c("steve", "1", "2.1", "3.2.1", "4.3.2.1")

# Technically, a "valid" semver string is MAJOR.MINOR.PATCH
is_valid_semver(versions)
```

    ## [1] FALSE  TRUE  TRUE  TRUE FALSE

``` r
complete_semver(versions)
```

    ## [1] "steve"   "1.0.0"   "2.1.0"   "3.2.1"   "4.3.2.1"

``` r
complete_semver(versions, quad=TRUE)
```

    ## [1] "steve"   "1.0.0.0" "2.1.0.0" "3.2.1.0" "4.3.2.1"

Apache

``` r


@@ 74,6 101,27 @@ apache_httpd_version_history()
    ## 10 1.3.14 2000-10-10     2000     1     3    14 ""         ""   
    ## # ... with 19 more rows

Apple iOS

``` r
apple_ios_version_history()
```

    ## # A tibble: 112 x 7
    ##    vers  rls_date   major minor patch prerelease build
    ##    <fct> <date>     <int> <int> <int> <chr>      <chr>
    ##  1 1.0.0 2007-06-29     1     0     0 ""         ""   
    ##  2 1.0.1 2007-07-31     1     0     1 ""         ""   
    ##  3 1.0.2 2007-08-21     1     0     2 ""         ""   
    ##  4 1.1.0 2007-09-14     1     1     0 ""         ""   
    ##  5 1.1.1 2007-09-27     1     1     1 ""         ""   
    ##  6 1.1.2 2007-11-12     1     1     2 ""         ""   
    ##  7 1.1.3 2008-01-15     1     1     3 ""         ""   
    ##  8 1.1.4 2008-02-26     1     1     4 ""         ""   
    ##  9 1.1.5 2008-07-15     1     1     5 ""         ""   
    ## 10 2.0.0 2008-07-11     2     0     0 ""         ""   
    ## # ... with 102 more rows

Google Chrome

``` r

A README_cache/gfm/apple_ios_c87a0ba8187fd58c6318fd9ff44ca2a6.RData => README_cache/gfm/apple_ios_c87a0ba8187fd58c6318fd9ff44ca2a6.RData +0 -0
A README_cache/gfm/apple_ios_c87a0ba8187fd58c6318fd9ff44ca2a6.rdb => README_cache/gfm/apple_ios_c87a0ba8187fd58c6318fd9ff44ca2a6.rdb +0 -0
A README_cache/gfm/apple_ios_c87a0ba8187fd58c6318fd9ff44ca2a6.rdx => README_cache/gfm/apple_ios_c87a0ba8187fd58c6318fd9ff44ca2a6.rdx +0 -0
A man/apple_ios_version_history.Rd => man/apple_ios_version_history.Rd +19 -0
@@ 0,0 1,19 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/ios.R
\name{apple_ios_version_history}
\alias{apple_ios_version_history}
\title{Retrieve Apple iOS  Version Release History}
\usage{
apple_ios_version_history()
}
\description{
Reads \url{https://en.wikipedia.org/wiki/IOS_version_history"} to build a data
frame of Apple iOS version release numbers and dates with pseudo-semantic version
strings parsed and separate fields added. The data frame is also arranged in
order from lowest version to latest version and the \code{vers} column is an
ordered factor.
}
\note{
This does not distinguish by device target and only pulls the first release
date and excludes betas. If more granular data is needed, file an issue or PR.
}

A man/complete_semver.Rd => man/complete_semver.Rd +23 -0
@@ 0,0 1,23 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/utils.R
\name{complete_semver}
\alias{complete_semver}
\title{Turn partial "valid" semantic version strings into a complete semver-tri or quad strings}
\usage{
complete_semver(x, quad = FALSE)
}
\arguments{
\item{x}{a character vector of full or partial version strings}

\item{quad}{(logical) if `TRUE` then a three-dot semver is returned, else a two-dot semver
is returned. Default: `FALSE`.}
}
\description{
For MAJOR.MINOR.PATCH (semver-tri), turn `1` into `1.0.0`; `1.1` into `1.1.0`; `1.1.1`
into `1.1.1`. For MAJOR.MINOR.PATCH.EXTENSION (semver-quad), turn `1` into `1.0.0.0`;
`1.1` into `1.1.0.0`; `1.1.1.0` into `1.1.1.0`.
}
\details{
Partial validity checking is performed to test if the input strings contain only
digits and periods. "Invalid" input is returned unscathed.
}

R man/is_valid.Rd => man/is_valid_semver.Rd +5 -5
@@ 1,14 1,14 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/RcppExports.R
\name{is_valid}
\alias{is_valid}
\title{Test if semantic version strings are valid}
\name{is_valid_semver}
\alias{is_valid_semver}
\title{Test if semantic version strings are valid tri-string}
\usage{
is_valid(v)
is_valid_semver(v)
}
\arguments{
\item{v}{character verctor of version strings}
}
\description{
Test if semantic version strings are valid
Test if semantic version strings are valid tri-string
}

M man/lighttpd_version_history.Rd => man/lighttpd_version_history.Rd +1 -1
@@ 10,6 10,6 @@ lighttpd_version_history()
Reads from the \code{lighttpd} releases and snapshot downloads to build a
data frame of version release numbers and dates. The caller is responsible
for extracting out the version components due to the non-standard
semantic versioning used. The \code{\link[=is_valid]{is_valid()}} function can be used to test the
semantic versioning used. The \code{\link[=is_valid_semver]{is_valid_semver()}} function can be used to test the
validity of version strings.
}

M src/RcppExports.cpp => src/RcppExports.cpp +5 -5
@@ 5,20 5,20 @@

using namespace Rcpp;

// is_valid
std::vector < bool > is_valid(std::vector < std::string > v);
RcppExport SEXP _vershist_is_valid(SEXP vSEXP) {
// is_valid_semver
std::vector < bool > is_valid_semver(std::vector < std::string > v);
RcppExport SEXP _vershist_is_valid_semver(SEXP vSEXP) {
BEGIN_RCPP
    Rcpp::RObject rcpp_result_gen;
    Rcpp::RNGScope rcpp_rngScope_gen;
    Rcpp::traits::input_parameter< std::vector < std::string > >::type v(vSEXP);
    rcpp_result_gen = Rcpp::wrap(is_valid(v));
    rcpp_result_gen = Rcpp::wrap(is_valid_semver(v));
    return rcpp_result_gen;
END_RCPP
}

static const R_CallMethodDef CallEntries[] = {
    {"_vershist_is_valid", (DL_FUNC) &_vershist_is_valid, 1},
    {"_vershist_is_valid_semver", (DL_FUNC) &_vershist_is_valid_semver, 1},
    {NULL, NULL, 0}
};


M src/vershist-main.cpp => src/vershist-main.cpp +2 -2
@@ 15,12 15,12 @@ bool one_is_valid(std::string v) {

}

//' Test if semantic version strings are valid
//' Test if semantic version strings are valid tri-string
//'
//' @param v character verctor of version strings
//' @export
// [[Rcpp::export]]
std::vector < bool > is_valid(std::vector < std::string > v) {
std::vector < bool > is_valid_semver(std::vector < std::string > v) {

  std::vector < bool > ret(v.size());