#' Does a source package have `src/` directory?
#'
#' If it does, you definitely need build tools.
#'
#' @param path Path to package (or directory within package).
#' @export
pkg_has_src <- function(path = ".") {
  if (is_dir(path)) {
    src_path <- file.path(pkg_path(path), "src")
    file.exists(src_path)
  } else {
    tryCatch(
      {
        files <- if (is_zip_file(path)) {
          utils::unzip(path, list = TRUE)$Name
        } else if (is_tar_gz_file(path)) {
          utils::untar(path, list = TRUE)
        } else {
          stop("not a zip or tar.gz file")
        }

        if (!any(grepl("^[^/]+/DESCRIPTION$", files))) {
          stop("no DESCRIPTION file")
        }

        any(grepl("^[^/]+/src/?$", files))
      },
      error = function(e) {
        e$message <- paste(
          path, "is not a valid package archive file,",
          e$message
        )
        stop(e)
      }
    )
  }
}

is_zip_file <- function(file) {
  buf <- readBin(file, what = "raw", n = 4)
  length(buf) == 4 &&
    buf[1] == 0x50 &&
    buf[2] == 0x4b &&
    (buf[3] == 0x03 || buf[3] == 0x05 || buf[5] == 0x07) &&
    (buf[4] == 0x04 || buf[4] == 0x06 || buf[4] == 0x08)
}

is_gz_file <- function(file) {
  buf <- readBin(file, what = "raw", n = 3)
  length(buf) == 3 &&
    buf[1] == 0x1f &&
    buf[2] == 0x8b &&
    buf[3] == 0x08
}

is_tar_gz_file <- function(file) {
  if (!is_gz_file(file)) {
    return(FALSE)
  }
  con <- gzfile(file, open = "rb")
  on.exit(close(con))
  buf <- readBin(con, what = "raw", n = 262)
  length(buf) == 262 &&
    buf[258] == 0x75 &&
    buf[259] == 0x73 &&
    buf[260] == 0x74 &&
    buf[261] == 0x61 &&
    buf[262] == 0x72
}
