1#' Author Signature
2#'
3#' A signature contains the author and timestamp of a commit. Each commit
4#' includes a signature of the author and committer (which can be identical).
5#'
6#' A signature string has format `"Real Name <email> timestamp tzoffset"`. The
7#' `timestamp tzoffset` piece can be omitted in which case the current local
8#' time is used. If not omitted, `timestamp` must contain the number
9#' of seconds since the Unix epoch and `tzoffset` is the timezone offset in
10#' `hhmm` format (note the lack of a colon separator)
11#'
12#' @export
13#' @rdname git_signature
14#' @name git_signature
15#' @family git
16#' @inheritParams git_open
17#' @useDynLib gert R_git_signature_default
18#' @examples # Your default user
19#' try(git_signature_default())
20#'
21#' # Specify explicit name and email
22#' git_signature("Some committer", "sarah@gmail.com")
23#'
24#' # Create signature for an hour ago
25#' (sig <- git_signature("Han", "han@company.com", Sys.time() - 3600))
26#'
27#' # Parse a signature
28#' git_signature_parse(sig)
29#' git_signature_parse("Emma <emma@mu.edu>")
30git_signature_default <- function(repo = '.'){
31  repo <- git_open(repo)
32  sig <- .Call(R_git_signature_default, repo)
33  sprintf("%s <%s>", sig$name, sig$email)
34}
35
36#' @export
37#' @rdname git_signature
38#' @useDynLib gert R_git_signature_create
39#' @param name Real name of the committer
40#' @param email Email address of the committer
41#' @param time timestamp of class POSIXt or NULL
42git_signature <- function(name, email, time = NULL){
43  assert_string(name)
44  assert_string(email)
45  if(length(time)){
46    time <- as.POSIXct(time)
47    tz <- format(time, "%z")
48    minutes <- as.integer(substring(tz, 4))
49    hours <- as.integer(substring(tz, 1, 3))
50    offset <- hours * 60 + minutes
51  }
52  sig <- .Call(R_git_signature_create, name, email, time, offset)
53  if(length(time)){
54    sig_data_to_string(sig)
55  } else {
56    sig_data_to_string(list(name = sig$name, email = sig$email))
57  }
58}
59
60#' @export
61#' @rdname git_signature
62#' @param sig string in proper `"First Last <your@email.com>"` format, see details.
63#' @useDynLib gert R_git_signature_parse
64git_signature_parse <- function(sig){
65  assert_string(sig)
66  .Call(R_git_signature_parse, sig)
67}
68
69offset_to_string <- function(offset){
70  if(length(offset) && is.numeric(offset)){
71    hours <- as.integer(offset %/% 60)
72    mins <- as.integer(offset %% 60)
73    sprintf('%+03d%02d', hours, mins)
74  } else ""
75}
76
77sig_data_to_string <- function(x){
78  sig <- sprintf("%s <%s>", x$name, x$email)
79  if(length(x$time)){
80    sig <- paste(sig, unclass(x$time), offset_to_string(x$offset))
81  }
82  structure(trimws(sig), class = "gert_signature")
83}
84
85#' @export
86print.gert_signature <- function(x, ...){
87  sig <- git_signature_parse(x)
88  name <- sig$name
89  email <- sig$email
90  time <- format(sig$time, "%a %b %d %H:%M:%S %Y") #print as user local time
91  offset <- offset_to_string(sig$offset)
92  cat(sprintf('[git signature]\nAuthor: %s <%s>\nDate: %s %s\n', name, email, time, offset))
93}
94