├── .Rbuildignore ├── .gitignore ├── .travis.yml ├── API ├── CONTRIBUTING.md ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── R ├── assert.R ├── data.R ├── detailed.R ├── engineer-features-base.R ├── enrich.R ├── extract_factories.R ├── gitsum-package.R ├── io.R ├── messages.R ├── nest.R ├── parse.R ├── patterns.R ├── raw_log.R ├── renamed-files.R ├── reports.R ├── simple.R ├── testing.R └── vis.R ├── README-ggplot1-1.png ├── README-ggplot2-1.png ├── README-ggplot3-1.png ├── README-per_file-1.png ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── appveyor.yml ├── benchmarking ├── alternatives ├── at_86acd.rds ├── at_86acd_dplyr.rds ├── at_86acd_dplyr_parse_one2.rds ├── at_86acd_dplyr_parse_one2_extract_multiple.rds ├── get_log_benchmarking.R └── primer.Rmd ├── data └── gitsumlog.rda ├── docs ├── LICENSE.html ├── README-ggplot1-1.png ├── README-ggplot2-1.png ├── README-ggplot3-1.png ├── README-per_file-1.png ├── articles │ ├── cached-logs.html │ ├── cached-logs_files │ │ └── figure-html │ │ │ ├── unnamed-chunk-1-1.png │ │ │ └── unnamed-chunk-1-2.png │ └── index.html ├── authors.html ├── index.html ├── jquery.sticky-kit.min.js ├── link.svg ├── pkgdown.css ├── pkgdown.js └── reference │ ├── add_line_history.html │ ├── check_overwriting_clearance.html │ ├── dump_parsed_log.html │ ├── ensure_gitsum_repo.html │ ├── extract_factory_multiple.html │ ├── find_message_and_desc.html │ ├── get_pattern_multiple.html │ ├── get_raw_log.html │ ├── git_report.html │ ├── gitsum.html │ ├── gitsumlog.html │ ├── index.html │ ├── log.html │ ├── manage_gitsum.html │ ├── parse_log_detailed.html │ ├── parse_log_one.html │ ├── parse_log_simple.html │ ├── read_gitsum.html │ ├── report_git.html │ └── testthat_file.html ├── gitsum.Rproj ├── index.Rmd ├── inst └── report_templates │ └── repo_summary_simple.Rmd ├── man ├── add_attributes_detailed.Rd ├── add_is_exact.Rd ├── add_line_history.Rd ├── add_n_times_changed_file.Rd ├── check_overwriting_clearance.Rd ├── combine_dir_and_base.Rd ├── combine_dir_and_base_one.Rd ├── dump_parsed_log.Rd ├── ensure_enclosing.Rd ├── ensure_gitsum_repo.Rd ├── expect_class.Rd ├── extract_factory_multiple.Rd ├── file_path.Rd ├── find_last_commit.Rd ├── find_message_and_desc.Rd ├── get_pattern_multiple.Rd ├── get_raw_log.Rd ├── gitsum.Rd ├── gitsumlog.Rd ├── group_reassignment.Rd ├── is_detailed_log.Rd ├── is_name_change.Rd ├── manage_gitsum.Rd ├── nest_log.Rd ├── parse_lines.Rd ├── parse_log_detailed.Rd ├── parse_log_one.Rd ├── parse_log_simple.Rd ├── parse_reassignment.Rd ├── parse_test_log.Rd ├── read_gitsum.Rd ├── report_git.Rd ├── separate_dir_and_reassignment.Rd ├── set_changed_file_to_latest_name.Rd ├── testthat_file.Rd ├── update_changed_file.Rd ├── update_changed_file_one.Rd └── update_changed_file_sequentially.Rd ├── tests ├── testthat.R └── testthat │ ├── reference-objects │ ├── combine-dir-and-base │ ├── nest │ ├── parse-reassignment │ ├── parse-reassignment-complex │ ├── parse-reassignment-complex2 │ ├── separate-dir-and-assignment │ └── unnest │ ├── test-assert-log.R │ ├── test-backend.R │ ├── test-dir-reports │ └── .gitsum │ │ ├── last_commit.rds │ │ └── log.rds │ ├── test-dir │ └── .gitsum │ │ ├── last_commit.rds │ │ └── log.rds │ ├── test-log_outputs.R │ ├── test-nest.R │ ├── test-renaming.R │ ├── test-report_generation.R │ ├── test-testing.R │ ├── test-type-stability.R │ └── test_logs │ ├── log_out_det.rds │ ├── log_out_simp.rds │ ├── testthat_log_detailed.txt │ └── testthat_log_simple.txt └── vignettes ├── .gitignore └── renaming.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^README\.Rmd$ 4 | ^README-.*\.png$ 5 | gitsum/ 6 | benchmarking 7 | .travis.yml 8 | ^appveyor\.yml$ 9 | ^docs$ 10 | ^API$ 11 | ^_pkgdown\.yml$ 12 | ^doc$ 13 | CONTRIBUTING.md 14 | index.Rmd 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | gitsum/ 6 | .gitsum/ 7 | benchmarking/*.html 8 | inst/doc 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: r 2 | cache: packages 3 | warnings_are_errors: false 4 | r_packages: 5 | - covr 6 | after_success: 7 | - Rscript -e 'library(covr); codecov()' 8 | notifications: 9 | slack: rcollaborators:vsKVUWorGw2xKn9H0yhPIC36 10 | -------------------------------------------------------------------------------- /API: -------------------------------------------------------------------------------- 1 | # API for gitsum package 2 | 3 | ## Exported functions 4 | 5 | add_line_history(log) 6 | add_n_times_changed_file(log) 7 | find_last_commit(path = ".", update_dump = FALSE) 8 | init_gitsum(path = ".", over_write = FALSE) 9 | nest_log(log) 10 | parse_log_detailed(path = ".", update_dump = TRUE) 11 | parse_log_detailed_full_run(path = ".", na_to_zero = TRUE, file_name = NULL, commit_range = NULL) 12 | parse_log_simple(path = ".", file_name = NULL) 13 | read_log(path = ".") 14 | remove_gitsum(path = ".") 15 | report_git(path = ".", output_file = NULL, output_format = "html_document", template = "gitsum::repo_summary_simple", input_file = NULL, directory = "gitsum", cached = TRUE, .libpath_index = 1) 16 | set_changed_file_to_latest_name(log) 17 | unnest_log(log) 18 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | This project follows the contributing recommendations outlined by [saamwerk](https://lorenzwalthert.github.io/saamwerk/). 2 | In particular, issues labelled with `Status: Postponed` are closed even if they are not resolved. 3 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: gitsum 2 | Type: Package 3 | Title: Parse and summarize git repositories 4 | Version: 0.0.9001 5 | Authors@R: person("Lorenz", "Walthert", 6 | email = "lorenz.walthert@icloud.com", role = c("aut", "cre")) 7 | Description: This package parses a git repository history to collect 8 | comprehensive information about the activity in the repo. The parsed 9 | data is made available to the user in a tabular format and can be used to 10 | create various statistics on the repository. Graphs, figures or even 11 | reports can be generated automatically. 12 | Roxygen: list(markdown = TRUE, roclets = c("rd", "namespace", "collate", "pkgapi::api_roclet")) 13 | License: MIT + file LICENSE 14 | Encoding: UTF-8 15 | LazyData: true 16 | RoxygenNote: 7.1.1 17 | Depends: R(>= 2.10) 18 | Imports: 19 | lubridate, 20 | cli, 21 | dplyr (>= 0.7), 22 | forcats, 23 | magrittr, 24 | readr, 25 | rlang, 26 | rmarkdown, 27 | tidyr (>= 1.0.0), 28 | purrr, 29 | tibble, 30 | stringr, 31 | rprojroot, 32 | ggplot2, 33 | hms 34 | Suggests: 35 | testthat, 36 | knitr 37 | VignetteBuilder: knitr 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Lorenz Walthert 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(add_line_history) 4 | export(add_n_times_changed_file) 5 | export(find_last_commit) 6 | export(init_gitsum) 7 | export(nest_log) 8 | export(parse_log_detailed) 9 | export(parse_log_detailed_full_run) 10 | export(parse_log_simple) 11 | export(remove_gitsum) 12 | export(report_git) 13 | export(set_changed_file_to_latest_name) 14 | export(unnest_log) 15 | import(ggplot2) 16 | importFrom(dplyr,arrange) 17 | importFrom(dplyr,as_data_frame) 18 | importFrom(dplyr,bind_rows) 19 | importFrom(dplyr,desc) 20 | importFrom(dplyr,do) 21 | importFrom(dplyr,everything) 22 | importFrom(dplyr,first) 23 | importFrom(dplyr,group_by) 24 | importFrom(dplyr,if_else) 25 | importFrom(dplyr,last) 26 | importFrom(dplyr,left_join) 27 | importFrom(dplyr,mutate) 28 | importFrom(dplyr,n) 29 | importFrom(dplyr,pull) 30 | importFrom(dplyr,rename) 31 | importFrom(dplyr,rowwise) 32 | importFrom(dplyr,select) 33 | importFrom(dplyr,select_) 34 | importFrom(dplyr,slice) 35 | importFrom(dplyr,summarize) 36 | importFrom(dplyr,ungroup) 37 | importFrom(forcats,fct_inorder) 38 | importFrom(hms,parse_hm) 39 | importFrom(lubridate,ymd_hms) 40 | importFrom(magrittr,"%>%") 41 | importFrom(purrr,compact) 42 | importFrom(purrr,flatten_chr) 43 | importFrom(purrr,map) 44 | importFrom(purrr,map2_lgl) 45 | importFrom(purrr,map_at) 46 | importFrom(purrr,partial) 47 | importFrom(purrr,pmap) 48 | importFrom(purrr,reduce) 49 | importFrom(purrr,walk) 50 | importFrom(purrr,when) 51 | importFrom(readr,read_delim) 52 | importFrom(readr,read_lines) 53 | importFrom(readr,read_rds) 54 | importFrom(readr,write_rds) 55 | importFrom(rlang,.data) 56 | importFrom(rlang,seq2) 57 | importFrom(rlang,set_names) 58 | importFrom(rlang,sym) 59 | importFrom(rmarkdown,render) 60 | importFrom(stringr,fixed) 61 | importFrom(stringr,str_length) 62 | importFrom(stringr,str_locate) 63 | importFrom(stringr,str_match) 64 | importFrom(stringr,str_split) 65 | importFrom(stringr,str_sub) 66 | importFrom(tibble,as_tibble) 67 | importFrom(tibble,data_frame) 68 | importFrom(tidyr,nest) 69 | importFrom(tidyr,separate) 70 | importFrom(tidyr,unnest) 71 | -------------------------------------------------------------------------------- /R/assert.R: -------------------------------------------------------------------------------- 1 | #' Check whether an object is a detailed log 2 | #' 3 | #' @param log The object to inspect. 4 | #' @param nested Whether or not the object to inspect should be nested or not. 5 | #' `NA` indicates that both nested and unnested logs shoud pass the 6 | #' inspection. 7 | #' @keywords internal 8 | is_detailed_log <- function(log, nested = NA) { 9 | expected_names_nested <- c( 10 | "short_hash", "author_name", "date", "short_message", "hash", 11 | "left_parent", "right_parent", "author_email", "weekday", "month", 12 | "monthday", "time", "year", "timezone", "message", "description", 13 | "total_files_changed", "total_insertions", "total_deletions", 14 | "commit_nr", "short_description", "is_merge", "nested" 15 | ) 16 | expected_names_unnested <- c( 17 | setdiff(expected_names_nested, "nested"), 18 | c("changed_file", "edits", "insertions", "deletions", "is_exact") 19 | ) 20 | 21 | is_nested_log <- expect_names(log, expected_names_nested) 22 | is_unnested_log <- expect_names(log, expected_names_unnested) 23 | if (is.na(nested)) { 24 | passes <- is_nested_log || is_unnested_log 25 | } else if (nested == TRUE) { 26 | passes <- is_nested_log 27 | } else { 28 | passes <- is_unnested_log 29 | } 30 | passes 31 | } 32 | 33 | #' @importFrom purrr when 34 | assert_detailed_log <- function(log, nested = NA) { 35 | msg <- when(nested, 36 | is.na(.) ~ "a", 37 | . ~ "a nested", 38 | !. ~ "an unnested" 39 | ) 40 | if (!is_detailed_log(log, nested)) { 41 | stop(paste("log is not", msg, "detailed log"), call. = FALSE) 42 | } 43 | } 44 | 45 | expect_names <- function(log, expected_names) { 46 | setequal(names(log), expected_names) 47 | } 48 | -------------------------------------------------------------------------------- /R/data.R: -------------------------------------------------------------------------------- 1 | #' Sample log data from git repository 2 | #' 3 | #' @name gitsumlog 4 | #' @docType data 5 | #' @author Lorenz Walthert 6 | #' @keywords data 7 | NULL 8 | -------------------------------------------------------------------------------- /R/detailed.R: -------------------------------------------------------------------------------- 1 | # ____________________________________________________________________________ 2 | # advanced log #### 3 | 4 | #' Obtain a detailed git log 5 | #' 6 | #' This function returns a git log in a tabular format. 7 | #' @inheritParams parse_log_simple 8 | #' @inheritParams get_raw_log 9 | #' @param na_to_zero Whether some `NA` values should be converted to zero. 10 | #' See 'Details'. 11 | #' @param update_dump Whether or not to update the dump in .gitsum after 12 | #' parsing. 13 | #' @details 14 | #' * Note that for merge commits, the following columns are `NA` if 15 | #' the option `na_to_zero` is set to `FALSE`.: 16 | #' total_files_changed, total_insertions, total_deletions, changed_file, 17 | #' edits, deletions, insertions. 18 | #' * Note that for binary files, the following columns are 0: edits, deletions, 19 | #' insertions. 20 | #' @section Warning: 21 | #' The number of edits, insertions, and deletions (on a file level) are based 22 | #' on `git log --stat` and the number of `+` and `-` in this log. The number 23 | #' of `+` and `-` may not sum up to the edits indicated as a scalar after "|" 24 | #' in `git log --stat` 25 | #' for commits with very many changed lines since for those, the `+` and `-` 26 | #' only indicate the relative share of insertions and edits. Therefore, 27 | #' `parse_log_detailed_full_run()` normalizes the insertions and deletions and rounds 28 | #' these after the normalization to achieve more consistent results. However, 29 | #' there is no guarantee that these numbers are always exact. The column 30 | #' is_exact indicates for each changed file within a commit whether the result 31 | #' is exact (which is the case if the normalizing constant was one). 32 | #' @return A parsed git log as a nested tibble. Each line corresponds to a 33 | #' commit. The unnested column names are: \cr 34 | #' short_hash, author_name, date, short_message, hash, left_parent, 35 | #' right_parent, author_email, weekday, month, monthday, time, year, timezone, 36 | #' message, description, total_files_changed, total_insertions, 37 | #' total_deletions, short_description, is_merge \cr 38 | #' The nested columns contain more information on each commit. The column 39 | #' names are: \cr 40 | #' changed_file, edits, insertions, deletions. 41 | #' @seealso See [parse_log_simple] for a fast alternative with less information. 42 | #' @importFrom dplyr mutate select everything group_by do last 43 | #' @importFrom lubridate ymd_hms 44 | #' @importFrom tidyr unnest nest 45 | #' @importFrom dplyr arrange ungroup bind_rows 46 | #' @export 47 | parse_log_detailed <- function(path = ".", update_dump = TRUE) { 48 | last_hash <- read_last_hash(path) 49 | new_log <- read_log(path) %>% 50 | bind_rows( 51 | parse_log_detailed_full_run(path, commit_range = paste0(last_hash, "..HEAD")) 52 | ) 53 | if (update_dump) { 54 | update_dump_from_log(new_log, path) 55 | } 56 | new_log 57 | } 58 | 59 | #' @describeIn parse_log_detailed In contrast to parse_log_detailed, this function 60 | #' does not read any history from the .gitum directory. 61 | #' @export 62 | parse_log_detailed_full_run <- function(path = ".", 63 | na_to_zero = TRUE, 64 | file_name = NULL, 65 | commit_range = NULL) { 66 | # create log 67 | lines <- get_raw_log(path, file_name, commit_range = commit_range) 68 | if (nrow(lines) < 1) return(tibble::tibble()) 69 | if (last(lines$lines) != "") { 70 | lines[nrow(lines) + 1, 1] <- "" 71 | } 72 | parsed_lines <- lines %>% 73 | parse_lines() 74 | out <- parsed_lines %>% 75 | type_convert_base_attributes() %>% 76 | add_attributes_detailed() %>% 77 | set_na_to_zero(na_to_zero) %>% 78 | nest_log() %>% 79 | select( 80 | .data$short_hash, .data$author_name, .data$date, 81 | .data$short_message, everything() 82 | ) %>% 83 | arrange(commit_nr) 84 | 85 | out 86 | } 87 | 88 | 89 | #' @importFrom purrr map_at 90 | #' @keywords internal 91 | set_na_to_zero <- function(log, 92 | na_to_zero = TRUE, 93 | columns = c( 94 | "edits", "insertions", "deletions", 95 | "total_files_changed", "total_insertions", 96 | "total_deletions" 97 | )) { 98 | if (!na_to_zero) return(log) 99 | out <- log %>% 100 | map_at(columns, if_na_to_zero) %>% 101 | tibble::as_tibble() 102 | out 103 | } 104 | 105 | if_na_to_zero <- function(vec) { 106 | ifelse(is.na(vec), 0L, vec) 107 | } 108 | -------------------------------------------------------------------------------- /R/engineer-features-base.R: -------------------------------------------------------------------------------- 1 | #' Add base attributes to a log 2 | #' 3 | #' @param log An unnested log. 4 | #' @details 5 | #' Derives some attributes from the parsed raw log and converts them to the 6 | #' desired format. 7 | #' The following attributes merit special mentioning: 8 | #' 9 | #' * commit_nr: The number of the commit in the repo. This can be used to sort 10 | #' commits (in contrast to the commit date) in chronological order, that is, 11 | #' in the oder in which they were committed. 12 | #' @keywords internal 13 | add_attributes_detailed <- function(log) { 14 | mutate(log, 15 | date = ymd_hms(paste(.data$year, .data$month, .data$monthday, .data$time)), 16 | short_hash = substr(.data$hash, 1, 4), 17 | short_message = substr(.data$message, 1, 20), 18 | short_description = ifelse(!is.na(.data$message), 19 | substr(.data$description, 1, 20), NA 20 | ), 21 | is_merge = ifelse(!is.na(.data$left_parent) & !is.na(.data$right_parent), 22 | TRUE, FALSE 23 | ) 24 | ) %>% 25 | add_is_exact() 26 | } 27 | 28 | #' @importFrom hms parse_hm 29 | type_convert_base_attributes <- function(log) { 30 | log %>% 31 | mutate( 32 | monthday = as.integer(.data$monthday), 33 | month = as.character(.data$month), 34 | hash = as.character(.data$hash), 35 | time = parse_hm(.data$time), 36 | year = as.integer(.data$year), 37 | total_files_changed = as.integer(.data$total_files_changed), 38 | total_insertions = as.integer(.data$total_insertions), 39 | total_deletions = as.integer(.data$total_deletions), 40 | edits = as.integer(ifelse(edits != "", .data$edits, 0)), 41 | insertions = ifelse(.data$insertions != "", nchar(.data$insertions), 0), 42 | deletions = ifelse(.data$deletions != "", nchar(.data$deletions), 0), 43 | changed_file = trimws(.data$changed_file) 44 | ) 45 | } 46 | 47 | #' Is the information exact? 48 | #' 49 | #' Create a column indicating whether insertions and deletions are exact counts. 50 | #' @inheritParams add_attributes_detailed 51 | #' @keywords internal 52 | add_is_exact <- function(log) { 53 | mutate(log, 54 | total_approx = .data$insertions + .data$deletions, 55 | multiplier = .data$edits / .data$total_approx, 56 | insertions = as.integer(round(.data$multiplier * .data$insertions)), 57 | deletions = as.integer(round(.data$multiplier * .data$deletions)), 58 | is_exact = if_else((is.na(.data$edits) | .data$multiplier == 1), TRUE, FALSE) 59 | ) %>% 60 | select(-.data$multiplier, -.data$total_approx) 61 | 62 | } 63 | -------------------------------------------------------------------------------- /R/enrich.R: -------------------------------------------------------------------------------- 1 | #' Add line history 2 | #' 3 | #' Add amount of lines added by each commits by file (insertions - deletions) 4 | #' plus number of total lines a file has according to past insertions and 5 | #' deletions (via [base::cumsum()]. 6 | #' @param log An unested gitsum log, for example obtained through 7 | #' [parse_log_detailed()]. 8 | #' @importFrom dplyr mutate group_by arrange 9 | #' @importFrom rlang .data 10 | #' @importFrom tidyr unnest 11 | #' @examples 12 | #' add_line_history(tidyr::unnest(gitsumlog)) 13 | #' @export 14 | add_line_history <- function(log) { 15 | log %>% 16 | mutate( 17 | lines_added = .data$insertions - .data$deletions, 18 | lines_added = ifelse(is.na(.data$lines_added), 0, .data$lines_added) 19 | ) %>% 20 | group_by(.data$changed_file) %>% 21 | mutate(current_lines = cumsum(.data$lines_added)) 22 | } 23 | 24 | #' How many times did file get changed? 25 | #' 26 | #' Add a variable `n_times_changed_file` to the unnested log, which contains 27 | #' the number of times a file was changed according to `log`. This may be 28 | #' helpful for subsetting. 29 | #' @param log An unnested log. 30 | #' @importFrom dplyr group_by summarize left_join n 31 | #' @export 32 | add_n_times_changed_file <- function(log) { 33 | stats <- log %>% 34 | group_by(.data$changed_file) %>% 35 | summarize(n_times_changed_file = n()) 36 | left_join(log, stats, by = "changed_file") 37 | } 38 | -------------------------------------------------------------------------------- /R/extract_factories.R: -------------------------------------------------------------------------------- 1 | #' closure to extract multiple regex pattern from vector 2 | #' 3 | #' @param pattern The pattern the function should be able to extract. 4 | #' @importFrom stringr str_match 5 | #' @keywords internal 6 | extract_factory_multiple <- function(pattern) { 7 | function(raw) { 8 | out <- str_match(raw, pattern)[, -1] 9 | out <- out[!is.na(out[, 1]), , drop = FALSE] 10 | if (length(out) == 0) { 11 | matrix(NA_character_, ncol = 4) 12 | } else { 13 | out 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /R/gitsum-package.R: -------------------------------------------------------------------------------- 1 | #' Parse and summarize a git repository 2 | #' 3 | #' @description `gitsum` provides tools to parse a git repository history and 4 | #' can create automated markdown reports from the parsed history. 5 | #' @author Lorenz Walthert \email{lorenz.walthert@@icloud.com}, \cr 6 | #' @name gitsum 7 | #' @docType package 8 | "_PACKAGE" 9 | if (getRversion() >= "2.15.1") utils::globalVariables(c(".")) 10 | -------------------------------------------------------------------------------- /R/io.R: -------------------------------------------------------------------------------- 1 | #' Manage a gitsum repository 2 | #' 3 | #' A gitsum repository is a git repository with an additional .gitsum folder in 4 | #' the root directory that is mainly used to store a parsed git log as a tibble. 5 | #' @param path The path to the repository to initialize. 6 | #' @param over_write Whether or not an existing directory should be overwritten. 7 | #' @name manage_gitsum 8 | #' @aliases init_gitsum remove_gitsum 9 | NULL 10 | 11 | #' @describeIn manage_gitsum Calling this function will parse the available git 12 | #' history and dump it into the directory .gitsum. 13 | #' @export 14 | init_gitsum <- function(path = ".", over_write = FALSE) { 15 | check_overwriting_clearance(gitsum_path(path), over_write, dir.exists) 16 | parse_log_detailed_full_run(path) %>% 17 | update_dump_from_log(path) 18 | } 19 | 20 | #' @describeIn manage_gitsum Removes the gitsum repository, i.e just the folder 21 | #' .gitsum and its contents. 22 | #' @export 23 | remove_gitsum <- function(path = ".") { 24 | was_gitsum_repo <- is_gitsum_repo(path) 25 | unlink(gitsum_path(path), recursive = TRUE) 26 | if (was_gitsum_repo) message(".gitsum removed.") 27 | } 28 | 29 | #' Dump a parsed log into .gitsum 30 | #' 31 | #' Store a parsed git log in a gitsum repository. 32 | #' @param log A parsed log as a tibble 33 | #' @param path The path to the root directory of the gitsum repository. 34 | #' @param verbose Whether or not to send informative messages to the console. 35 | #' @inheritParams check_overwriting_clearance 36 | #' @importFrom readr write_rds 37 | #' @keywords internal 38 | dump_parsed_log <- function(log, path = ".", over_write = FALSE, verbose = TRUE) { 39 | gitsum_path <- ensure_gitsum_repo(path) 40 | gitsum_path_log <- file.path(gitsum_path, "log.rds") 41 | check_overwriting_clearance(gitsum_path_log, over_write) 42 | write_rds(log, gitsum_path_log) 43 | if (verbose) message("\nLog created at ", gitsum_path_log) 44 | } 45 | 46 | 47 | #' @describeIn dump_parsed_log Dumps the last commit into .gitsum 48 | #' @importFrom readr write_rds 49 | #' @importFrom dplyr slice arrange desc 50 | #' @keywords internal 51 | dump_last_commit <- function(log, path, verbose = TRUE) { 52 | gitsum_path_last_commit <- gitsum_path(path, "last_commit.rds") 53 | last <- log %>% 54 | arrange(desc(.data$commit_nr)) %>% 55 | slice(1) 56 | write_rds(last, gitsum_path_last_commit) 57 | if (verbose) message("\nlast_commit saved at ", gitsum_path_last_commit) 58 | } 59 | 60 | #' Make sure the repository is a gitsum repository and create one if it is not 61 | #' @inheritParams dump_parsed_log 62 | #' @keywords internal 63 | ensure_gitsum_repo <- function(path = ".") { 64 | if (!is_gitsum_repo(path)) { 65 | dir.create(gitsum_path(path)) 66 | } 67 | gitsum_path(path) 68 | } 69 | 70 | #' Check whether a file / path exists and return an error when it cannot be 71 | #' overwritten. 72 | #' @inheritParams dump_parsed_log 73 | #' @param over_write Whether or not existing files / directories should be 74 | #' overwritten. 75 | #' @param fun The function to apply to the path, either file.exists, or 76 | #' dir.exists. 77 | #' @keywords internal 78 | check_overwriting_clearance <- function(path, over_write, fun = file.exists) { 79 | if (fun(path)) { 80 | if (!over_write) { 81 | stop( 82 | "Cannot overwrite file / path ", path, 83 | " since argument overwrite was set to FALSE" 84 | ) 85 | } 86 | } 87 | } 88 | 89 | #' Read gitsum data into R 90 | #' @inheritParams dump_parsed_log 91 | #' @name read_gitsum 92 | NULL 93 | 94 | #' @describeIn read_gitsum Reads a parsed log. 95 | #' @keywords internal 96 | read_log <- function(path = ".") { 97 | read_gitsum_data(path, "log.rds") 98 | } 99 | 100 | #' @describeIn read_gitsum Reads the last parsed commit. 101 | #' @keywords internal 102 | read_last_commit <- function(path = ".") { 103 | read_gitsum_data(path, "last_commit.rds") 104 | } 105 | 106 | #' Find the last commit in a repo 107 | #' 108 | #' Finds the last commit in a repo and optionally updates the dump. 109 | #' @inheritParams parse_log_detailed 110 | #' @export 111 | #' @importFrom dplyr arrange desc slice 112 | find_last_commit <- function(path = ".", update_dump = FALSE) { 113 | parse_log_detailed(path, update_dump) %>% 114 | arrange(desc(.data$commit_nr)) %>% 115 | slice(1) 116 | } 117 | 118 | #' @describeIn read_gitsum Reads the last parsed hash. 119 | #' @keywords internal 120 | read_last_hash <- function(path = ".") { 121 | last_commit <- read_last_commit(path) 122 | last_commit$hash 123 | } 124 | 125 | 126 | 127 | udpate_dump <- function(path = ".") { 128 | parse_log_detailed(path, update_dump = TRUE) 129 | invisible() 130 | } 131 | update_dump_from_log <- function(log, path) { 132 | dump_parsed_log(log, path, over_write = TRUE, verbose = FALSE) 133 | dump_last_commit(log, path, verbose = FALSE) 134 | } 135 | 136 | #' @importFrom readr read_rds 137 | read_gitsum_data <- function(path, ...) { 138 | assert_gitsum_repo(path) 139 | read_rds(gitsum_path(path, ...)) 140 | } 141 | 142 | is_gitsum_repo <- function(path = ".") { 143 | dir.exists(gitsum_path(path)) 144 | } 145 | 146 | gitsum_path <- function(path = ".", ...) { 147 | file.path(path, ".gitsum", ...) 148 | } 149 | assert_gitsum_repo <- function(path = ".") { 150 | if (!is_gitsum_repo(path)) init_gitsum(path) 151 | } 152 | -------------------------------------------------------------------------------- /R/messages.R: -------------------------------------------------------------------------------- 1 | #' extract message or description from a log 2 | #' 3 | #' For message and description extraction, a different approach is used and 4 | #' one cannot rely on the approach with the simple extraction factory. 5 | #' @param raw A character vector corresponding to one commit. 6 | #' @param target either "message" or "description 7 | #' @keywords internal 8 | find_message_and_desc <- function(raw, target) { 9 | message_and_desc_sep <- which(raw == "") 10 | message_start <- message_and_desc_sep[1] + 1 11 | message_end <- message_and_desc_sep[2] - 1 12 | desc_sep <- which(raw == " ")[1] 13 | if (is.na(desc_sep)) { 14 | c(paste(substring(raw[message_start:message_end], 5), collapse = "\n"), NA) 15 | } else { 16 | # if one line has just four spaces, we have both message and description 17 | c( 18 | paste(substring(raw[message_start:(desc_sep - 1)], 5), collapse = "\n"), 19 | paste(substring(raw[(desc_sep + 1):message_end], 5), collapse = "\n") 20 | ) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /R/nest.R: -------------------------------------------------------------------------------- 1 | #' Nest/unnest a gitsum log 2 | #' 3 | #' Forwards to [tidyr::nest()] while taking care of which columns have to be 4 | #' nested. 5 | #' @param log A log to nest/unnest. 6 | #' @export 7 | #' @importFrom tidyr nest 8 | nest_log <- function(log) { 9 | assert_detailed_log(log) 10 | if (is_detailed_log(log, nested = FALSE)) { 11 | log <- nest( 12 | log, 13 | "nested" = c( 14 | .data$changed_file, .data$edits, .data$insertions, 15 | .data$deletions, .data$is_exact) 16 | ) 17 | } else { 18 | warning("log was already nested, returning input log.", call. = FALSE) 19 | } 20 | log 21 | } 22 | 23 | #' Nest/unnest a gitsum log 24 | #' 25 | #' Forwards to [tidyr::unnest()] while taking care of which columns have to be 26 | #' nested unnested. 27 | #' @inheritParams nest_log 28 | #' @rdname nest_log 29 | #' @export 30 | unnest_log <- function(log) { 31 | assert_detailed_log(log) 32 | if (is_detailed_log(log, nested = TRUE)) { 33 | log <- unnest(log, .data$nested) 34 | } else { 35 | warning("log was already unnested, returning input log.", call. = FALSE) 36 | } 37 | log 38 | } 39 | -------------------------------------------------------------------------------- /R/parse.R: -------------------------------------------------------------------------------- 1 | #' parse a raw log 2 | #' 3 | #' @param raw a character vector corresponding to one commit. 4 | #' @param fnc_list the list of named functions that return the elements 5 | #' we want to extract from the log, i.e. author, hash etc. 6 | #' @param has_merge Whether or not `raw` is a merge commit. This is relevant 7 | #' because merge commits have additional lines. 8 | #' @importFrom stringr str_split str_sub 9 | #' @importFrom tibble data_frame 10 | #' @keywords internal 11 | parse_log_one <- function(raw, fnc_list, has_merge) { 12 | if (has_merge) { 13 | count <- 3 14 | } else { 15 | count <- 2 16 | } 17 | commit <- str_split(raw[1], " ", simplify = TRUE) 18 | author <- str_split(raw[count], " ", simplify = TRUE) 19 | date <- str_split(raw[count + 1], " ", simplify = TRUE) 20 | other <- raw[-c(1:(count + 1))] 21 | all_changes <- fnc_list$all_changes(other) 22 | all_changes_file <- fnc_list$all_changes_file(other) 23 | ms <- fnc_list$message_and_description(other) 24 | tibble::tibble( 25 | hash = commit[2], 26 | left_parent = commit[3], 27 | right_parent = commit[4], 28 | author_name = paste(author[2:(length(author) - 1)], collapse = " "), 29 | author_email = str_sub(author[length(author)], 2, -1), 30 | weekday = date[4], 31 | month = date[5], 32 | monthday = date[6], 33 | time = date[7], 34 | year = date[8], 35 | timezone = date[9], 36 | message = ms[1], 37 | description = ms[2], 38 | total_files_changed = all_changes[, 1], 39 | total_insertions = all_changes[, 2], 40 | total_deletions = all_changes[, 3], 41 | changed_file = all_changes_file[, 1], 42 | edits = all_changes_file[, 2], 43 | insertions = all_changes_file[, 3], 44 | deletions = all_changes_file[, 4] 45 | ) 46 | } 47 | 48 | #' Turn a raw log of lines into a tabular format 49 | #' 50 | #' @param lines The output of [get_raw_log()]. 51 | #' @importFrom rlang set_names 52 | #' @keywords internal 53 | parse_lines <- function(lines) { 54 | extractors <- set_names( 55 | c( 56 | find_message_and_desc, 57 | lapply(get_pattern_multiple(), extract_factory_multiple) 58 | ), nm = c("message_and_description", names(get_pattern_multiple())) 59 | ) 60 | 61 | lines %>% 62 | mutate( 63 | level = cumsum(grepl("^commit", .data$lines)), 64 | has_merge = grepl("^Merge:", .data$lines) 65 | ) %>% 66 | group_by(.data$level) %>% 67 | do(nested = parse_log_one(.$lines, extractors, any(.$has_merge))) %>% 68 | ungroup() %>% 69 | mutate(commit_nr = seq(nrow(.), 1L)) %>% 70 | select(-.data$level) %>% 71 | unnest(.data$nested) 72 | } 73 | -------------------------------------------------------------------------------- /R/patterns.R: -------------------------------------------------------------------------------- 1 | #' regex patterns for extraction 2 | #' 3 | #' @return returns a named vector with regex patterns to extract from a 4 | #' git log. 5 | #' @keywords internal 6 | get_pattern_multiple <- function() { 7 | c( 8 | all_changes = paste0( 9 | "^\\s(\\d+)\\sfiles?\\schanged,?\\s?(\\d+)?", 10 | "\\s?i?n?s?e?r?t?i?o?n?s?\\(?\\+?\\)?,", 11 | "?\\s?(\\d+)?\\s?d?e?l?e?t?i?o?n?s?", 12 | "\\(?\\-?\\)?$" 13 | ), 14 | all_changes_file = "^\\s(.*)\\s+\\|\\s*(\\d+)*\\s*(\\+*)(\\-*)" 15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /R/raw_log.R: -------------------------------------------------------------------------------- 1 | #' Obtain the log raw data 2 | #' @param path The path to the git directory one wants to create summaries for. 3 | #' @param file_name The name of the temporary file. If `NULL`, a file is 4 | #' created, otherwise, a file is read. 5 | #' @param remove Whether a log should be deleted after read in. 6 | #' @param commit_range A string of the form "hash1..hash2" indicating the commit 7 | #' range to parse. `NULL` means all commits. 8 | #' @importFrom readr read_lines 9 | #' @keywords internal 10 | get_raw_log <- function(path, 11 | file_name = NULL, 12 | remove = is.null(file_name), 13 | commit_range = NULL) { 14 | file_name_progr <- ifelse(is.null(file_name), ".log.txt", file_name) 15 | 16 | if (is.null(file_name)) { 17 | sys_call <- paste( 18 | "cd", path, "&&", 19 | "git log ", commit_range, " --stat --parents ", 20 | "--stat-width 99999", 21 | " >", file_name_progr 22 | ) 23 | if (Sys.info()[1] == "Windows") { 24 | error <- shell(sys_call) 25 | } else { 26 | error <- system(sys_call) 27 | } 28 | if (error == 128) stop(path, " is not a git repository") 29 | } 30 | 31 | # get list of commits 32 | path_to_file <- normalizePath(file.path(path, file_name_progr)) 33 | temp <- read_lines(path_to_file, progress = TRUE) 34 | if (remove) unlink(path_to_file) 35 | 36 | tibble::tibble(lines = temp) 37 | } 38 | -------------------------------------------------------------------------------- /R/reports.R: -------------------------------------------------------------------------------- 1 | #' Create a summary report of a git repository 2 | #' 3 | #' Producing a summary report of a repo. 4 | #' @param input_file the name of the temporary file that contains log data on 5 | #' which the report is base on. If `NULL`, a log file is created according to 6 | #' `path`, otherwise, a file is read. 7 | #' @param .libpath_index index of the Library according to [base::libPaths] in 8 | #' which the template should be searched. The list with the available 9 | #' directories is returned invisibly for situations in which `.libPaths()` 10 | #' cannot be emulated. 11 | #' @param template the template file to be used. Either one from a package 12 | #' (e.g. `gitsum::repo_summary_simple`), or a user defined template, 13 | #' which is then indicated with a path to this file including extension, i.e. 14 | #' `/users/xzy/a_template.Rmd`. 15 | #' @param directory A directory to which the reports should be stored. 16 | #' @param cached Whether or not the report should be cached with rmarkdown, so 17 | #' the graphs are written to a file. 18 | #' @details Other packages can define templates. They must be store an .Rmd 19 | #' template in inst/report_templates. The data passed to the report template 20 | #' is log, the parsed log table. 21 | #' @inheritParams get_raw_log 22 | #' @inheritParams rmarkdown::render 23 | #' @importFrom rmarkdown render 24 | #' @import ggplot2 25 | #' @export 26 | report_git <- function(path = ".", output_file = NULL, 27 | output_format = "html_document", 28 | template = "gitsum::repo_summary_simple", 29 | input_file = NULL, 30 | directory = "gitsum", cached = TRUE, 31 | .libpath_index = 1) { 32 | if (cached) { 33 | ensure_gitsum_repo(path) 34 | log <- parse_log_detailed(path = path) 35 | } else { 36 | log <- parse_log_detailed_full_run(path = path, file_name = input_file) 37 | } 38 | 39 | libpath <- .libPaths()[.libpath_index] 40 | 41 | template <- strsplit(template, "::", fixed = TRUE)[[1]] 42 | if (length(template) == 2) { 43 | path_in <- paste0(file.path( 44 | libpath, template[1], "report_templates", 45 | template[2] 46 | ), ".Rmd", collapse = "") 47 | } else { 48 | path_in <- path.expand(template) 49 | } 50 | 51 | if (!file.exists(path_in)) stop("template ", path_in, " does not exist.") 52 | 53 | if (!dir.exists(directory)) { 54 | dir.create(directory) 55 | message("created directory ", directory) 56 | } 57 | 58 | rmarkdown::render( 59 | input = path_in, # file 2 60 | output_format = output_format, 61 | output_file = output_file, 62 | output_dir = "./gitsum", quiet = TRUE 63 | ) 64 | 65 | message("reports saved in ", directory) 66 | invisible(libpath) 67 | } 68 | -------------------------------------------------------------------------------- /R/simple.R: -------------------------------------------------------------------------------- 1 | # ____________________________________________________________________________ 2 | # simple log #### 3 | 4 | #' Obtain a simple log for a git repo 5 | #' 6 | #' This function returns a git log in a tabular format. 7 | #' @inheritParams get_raw_log 8 | #' @param file_name The path to a raw log. If `NULL`, a raw log is created and 9 | #' read in and deleted after read-in, otherwise, an existing log is read. 10 | #' @seealso See [parse_log_detailed] for a slower alternative with more 11 | #' information. 12 | #' @importFrom readr read_delim 13 | #' @importFrom tidyr separate 14 | #' @importFrom dplyr mutate select_ if_else rowwise rename 15 | #' @importFrom dplyr everything arrange 16 | #' @importFrom lubridate ymd_hms 17 | #' @importFrom magrittr %>% 18 | #' @export 19 | parse_log_simple <- function(path = ".", file_name = NULL) { 20 | file_name_prog <- ifelse(is.null(file_name), 21 | "commits.local.tsv.txt", file_name 22 | ) 23 | 24 | if (is.null(file_name)) { 25 | if (file.exists(file_name_prog)) { 26 | message("file ", file_name_prog, " overwritten") 27 | } 28 | sys_call <- paste( 29 | "cd", path, "&&", "git log", 30 | "--date=local", 31 | "--pretty=format:'%h%x09%an%x09%ad%x09%s%x09%P' >", 32 | file_name_prog 33 | ) 34 | if (Sys.info()[1] == "Windows") { 35 | shell(sys_call) 36 | } else { 37 | system(sys_call) 38 | } 39 | } 40 | 41 | time <- c("weekday", "month", "monthday", "time", "year") 42 | log <- read_delim( 43 | file.path(path, file_name_prog), 44 | delim = "\t", 45 | col_names = c( 46 | "commit", 47 | "author", 48 | "date", 49 | "message", "parents" 50 | ), 51 | col_types = "ccccc" 52 | ) %>% 53 | separate(.data$date, into = time, sep = " ") %>% 54 | separate( 55 | .data$parents, into = c("left_parent", "right_parent"), sep = " ", 56 | fill = "right" 57 | ) %>% 58 | mutate( 59 | final_date = ymd_hms(paste( 60 | .data$year, .data$weekday, .data$month, .data$monthday, .data$time 61 | )), 62 | message_short = substr(.data$message, 1, 20) 63 | ) %>% 64 | rowwise() %>% 65 | mutate(n_parents = sum( 66 | !is.na(.data$left_parent), !is.na(.data$right_parent)) 67 | ) %>% 68 | ungroup() %>% 69 | rename(date = .data$final_date) %>% 70 | select(.data$author, .data$message_short, .data$date, everything()) %>% 71 | arrange(.data$date) 72 | if (is.null(file_name)) unlink(file.path(path, file_name_prog)) 73 | log 74 | } 75 | -------------------------------------------------------------------------------- /R/testing.R: -------------------------------------------------------------------------------- 1 | #' Create the path to a test that file 2 | #' @param ... Arguments passed to [file.path()] to construct the path after 3 | #' ".../tests/testthat/" 4 | #' @keywords internal 5 | testthat_file <- function(...) { 6 | file.path(rprojroot::find_testthat_root_file(), ...) 7 | } 8 | 9 | #' Parse a test log 10 | #' 11 | #' Function to facilitate the reading and parsing of a raw log for unit test 12 | #' purposes. 13 | #' @param path_to_raw_log The path to the raw log relative to tests/testthat/. 14 | #' @param ... Params passed to [parse_log_detailed_full_run()]. 15 | #' @param parser The parser to use, i.e. either [parse_log_detailed_full_run()] 16 | #' or [parse_log_simple()]. 17 | #' @keywords internal 18 | parse_test_log <- function(path_to_raw_log, parser = parse_log_detailed_full_run, ...) { 19 | path <- testthat_file(path_to_raw_log) 20 | parser( 21 | path = dirname(path), 22 | file_name = basename(path), 23 | ... 24 | ) 25 | } 26 | 27 | #' @importFrom purrr partial 28 | parse_test_log_detailed <- partial(parse_test_log, parser = parse_log_detailed_full_run) 29 | parse_test_log_simple <- partial(parse_test_log, parser = parse_log_simple) 30 | 31 | #' Class validation 32 | #' 33 | #' Check whether columns of a data frame match are of a certain class and return 34 | #' an informative warning otherwise. 35 | #' @param data A data frame to check. 36 | #' @param class_mapping A data frame that contains two columns: name and class, 37 | #' whereas the values in name indicate the name of a column to check, class 38 | #' indicates the target class of the column. 39 | #' @param must_check_all Whether or not all columns need to be checked in order 40 | #' to avoid a warning. 41 | #' @examples 42 | #' library(tibble) 43 | #' library(magrittr) 44 | #' class_mapping <- tribble( 45 | #' ~ name, ~ class, 46 | #' "cyl", "integer", 47 | #' "model", "character" 48 | #' ) 49 | #' rownames_to_column(mtcars, var= "model") %>% 50 | #' gitsum:::expect_class(class_mapping, must_check_all = FALSE) 51 | #' @importFrom purrr map2_lgl 52 | #' @importFrom tibble as_tibble 53 | #' @importFrom dplyr pull 54 | #' @keywords internal 55 | expect_class <- function(data, class_mapping, must_check_all) { 56 | class_mapping <- as_tibble(class_mapping) 57 | is_correct_class <- map2_lgl( 58 | pull(class_mapping, .data$name), pull(class_mapping, .data$class), 59 | expect_class_one, as_tibble(data) 60 | ) 61 | if (must_check_all) { 62 | diff <- setdiff(names(data), class_mapping$name) 63 | if (length(diff) > 0) 64 | stop( 65 | "All columns were required to be checked, but the following were not: ", 66 | paste(diff, collapse = ", "), call. = FALSE 67 | ) 68 | } 69 | } 70 | 71 | #' @importFrom dplyr first pull 72 | #' @importFrom rlang sym 73 | #' @keywords internal 74 | expect_class_one <- function(name, class, data) { 75 | cls <- pull(data, !!sym(name)) %>% 76 | class() %>% 77 | first() 78 | 79 | if (cls != class) { 80 | warning( 81 | paste0("class for ", name, " was ", cls, ", but ", class, " was expected"), 82 | call. = FALSE 83 | ) 84 | } 85 | cls == class 86 | } 87 | -------------------------------------------------------------------------------- /R/vis.R: -------------------------------------------------------------------------------- 1 | #' commits_by_author <- function(log) { 2 | #' ggplot(log, aes(x = author)) + geom_bar() + coord_flip() 3 | #' } 4 | #' commits_by_author(log) 5 | #' 6 | #' 7 | #' #' show commits over time 8 | #' #' 9 | #' #' @param log a log table. 10 | #' #' @param binsize The size of the bins in days. 11 | #' #' @param by_author Whether or not to show commits by author. 12 | #' commits_over_time <- function(log, binwidth = 1, by_author = TRUE) { 13 | #' binwidth <- 60*60*24 * binwidth 14 | #' fill <- NULL 15 | #' if (by_author) fill <- as.name("author") 16 | #' ggplot(log, aes_(x = as.name("final_date"), fill = fill)) + 17 | #' geom_histogram(binwidth = binwidth, position = "stack") 18 | #' } 19 | #' commits_over_time(log, 7) 20 | #' 21 | #' log %>% 22 | #' group_by(author) %>% 23 | #' count() 24 | -------------------------------------------------------------------------------- /README-ggplot1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/README-ggplot1-1.png -------------------------------------------------------------------------------- /README-ggplot2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/README-ggplot2-1.png -------------------------------------------------------------------------------- /README-ggplot3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/README-ggplot3-1.png -------------------------------------------------------------------------------- /README-per_file-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/README-per_file-1.png -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, echo = FALSE, message=FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "README-" 12 | ) 13 | ``` 14 | 15 | *Package is work in progress! If you encounter errors / 16 | problems, please file an issue or make a PR.* 17 | 18 | ![](https://img.shields.io/badge/lifecycle-experimental-orange.svg) 19 | [![codecov](https://codecov.io/gh/lorenzwalthert/gitsum/branch/master/graph/badge.svg)](https://codecov.io/gh/lorenzwalthert/gitsum) 20 | [![Build Status](https://travis-ci.org/lorenzwalthert/gitsum.svg?branch=master)](https://travis-ci.org/lorenzwalthert/gitsum) 21 | [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/lorenzwalthert/gitsum?branch=master&svg=true)](https://ci.appveyor.com/project/lorenzwalthert/gitsum) 22 | 23 | # Introduction 24 | This package parses a git repository history to collect 25 | comprehensive information about the activity in the repo. The parsed 26 | data is made available to the user in a tabular format. The package can also 27 | generate reports based on the parse data. You can install the development 28 | version from GitHub. 29 | 30 | ```{r, eval=FALSE} 31 | remotes::install_github("lorenzwalthert/gitsum") 32 | ``` 33 | 34 | There are two main functions for parsing the history, both return tabular data: 35 | 36 | * `parse_log_simple()` is a relatively fast parser and returns a tibble with 37 | one commit per row. There is no file-specific information. 38 | * `parse_log_detailed()` outputs a nested tibble and for each commit, the names 39 | of the amended files, number of lines changed ect. available. This function 40 | is slower. 41 | 42 | `report_git()` creates a html, pdf, or word report with the parsed log data 43 | according to a template. Templates can be created by the user or a template 44 | from the `gitsum` package can be used. 45 | 46 | Let's see the package in action. 47 | 48 | ```{r, message=FALSE, warning=FALSE} 49 | library("gitsum") 50 | library("tidyverse") 51 | library("forcats") 52 | ``` 53 | 54 | We can obtain a parsed log like this: 55 | 56 | ```{r, include=FALSE} 57 | remove_gitsum() 58 | ``` 59 | 60 | ```{r} 61 | init_gitsum() 62 | tbl <- parse_log_detailed() %>% 63 | select(short_hash, short_message, total_files_changed, nested) 64 | tbl 65 | ``` 66 | 67 | Since we used `parse_log_detailed()`, there is detailed file-specific 68 | information available for every commit: 69 | 70 | ```{r} 71 | tbl$nested[[3]] 72 | ``` 73 | 74 | Since the data has such a high resolution, various graphs, tables etc. can be 75 | produced from it to provide insights into the git history. 76 | 77 | # Examples 78 | Since the output of `git_log_detailed()` is a nested tibble, you can work on it 79 | as you work on any other tibble. 80 | Let us first have a look at who comitted to this repository: 81 | ```{r} 82 | log <- parse_log_detailed() 83 | log %>% 84 | group_by(author_name) %>% 85 | summarize(n = n()) 86 | ``` 87 | 88 | We can also investigate how the number of lines of each file in the R 89 | directory evolved. For that, we probaly want to view files with changed names 90 | as one file. Also, we probably don't want to see boring plots for files that 91 | got changed only a few times. Let's focus on files that were changed in 92 | at least five commits. 93 | ```{r per_file, message=FALSE, warning=FALSE} 94 | lines <- log %>% 95 | unnest_log() %>% 96 | set_changed_file_to_latest_name() %>% 97 | add_line_history() 98 | 99 | r_files <- grep("^R/", lines$changed_file, value = TRUE) 100 | 101 | to_plot <- lines %>% 102 | filter(changed_file %in% r_files) %>% 103 | add_n_times_changed_file() %>% 104 | filter(n_times_changed_file >= 10) 105 | ggplot(to_plot, aes(x = date, y = current_lines)) + 106 | geom_step() + 107 | scale_y_continuous(name = "Number of Lines", limits = c(0, NA)) + 108 | facet_wrap(~changed_file, scales = "free_y") 109 | ``` 110 | 111 | 112 | Next, we want to see which files were contained in most commits: 113 | ```{r ggplot1} 114 | log %>% 115 | unnest_log() %>% 116 | mutate(changed_file = fct_lump(fct_infreq(changed_file), n = 10)) %>% 117 | filter(changed_file != "Other") %>% 118 | ggplot(aes(x = changed_file)) + geom_bar() + coord_flip() + 119 | theme_minimal() 120 | ``` 121 | 122 | We can also easily get a visual overview of the number of insertions & deletions in commits over time: 123 | ```{r ggplot2} 124 | commit.dat <- data.frame( 125 | edits = rep(c("Insertions", "Deletions"), each = nrow(log)), 126 | commit = rep(1:nrow(log), 2), 127 | count = c(log$total_insertions, -log$total_deletions)) 128 | 129 | ggplot(commit.dat, aes(x = commit, y = count, fill = edits)) + 130 | geom_bar(stat = "identity", position = "identity") + 131 | theme_minimal() 132 | ``` 133 | 134 | Or the number of commits broken down by day of the week: 135 | ```{r ggplot3} 136 | log %>% 137 | mutate(weekday = factor(weekday, c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"))) %>% 138 | ggplot(aes(x = weekday)) + geom_bar() + 139 | theme_minimal() 140 | ``` 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | *Package is work in progress\! If you encounter errors / problems, 5 | please file an issue or make a PR.* 6 | 7 | ![](https://img.shields.io/badge/lifecycle-experimental-orange.svg) 8 | [![codecov](https://codecov.io/gh/lorenzwalthert/gitsum/branch/master/graph/badge.svg)](https://codecov.io/gh/lorenzwalthert/gitsum) 9 | [![Build 10 | Status](https://travis-ci.org/lorenzwalthert/gitsum.svg?branch=master)](https://travis-ci.org/lorenzwalthert/gitsum) 11 | [![AppVeyor Build 12 | Status](https://ci.appveyor.com/api/projects/status/github/lorenzwalthert/gitsum?branch=master&svg=true)](https://ci.appveyor.com/project/lorenzwalthert/gitsum) 13 | 14 | # Introduction 15 | 16 | This package parses a git repository history to collect comprehensive 17 | information about the activity in the repo. The parsed data is made 18 | available to the user in a tabular format. The package can also generate 19 | reports based on the parse data. You can install the development version 20 | from GitHub. 21 | 22 | ``` r 23 | remotes::install_github("lorenzwalthert/gitsum") 24 | ``` 25 | 26 | There are two main functions for parsing the history, both return 27 | tabular data: 28 | 29 | - `parse_log_simple()` is a relatively fast parser and returns a 30 | tibble with one commit per row. There is no file-specific 31 | information. 32 | - `parse_log_detailed()` outputs a nested tibble and for each commit, 33 | the names of the amended files, number of lines changed ect. 34 | available. This function is slower. 35 | 36 | `report_git()` creates a html, pdf, or word report with the parsed log 37 | data according to a template. Templates can be created by the user or a 38 | template from the `gitsum` package can be used. 39 | 40 | Let’s see the package in action. 41 | 42 | ``` r 43 | library("gitsum") 44 | library("tidyverse") 45 | library("forcats") 46 | ``` 47 | 48 | We can obtain a parsed log like this: 49 | 50 | ``` r 51 | init_gitsum() 52 | tbl <- parse_log_detailed() %>% 53 | select(short_hash, short_message, total_files_changed, nested) 54 | tbl 55 | #> # A tibble: 149 x 4 56 | #> short_hash short_message total_files_changed nested 57 | #> 58 | #> 1 243f initial commit 7 59 | #> 2 f8ee add log example data 1 60 | #> 3 6328 add parents 3 61 | #> 4 dfab intermediate 1 62 | #> 5 7825 add licence 1 63 | #> 6 2ac3 add readme 2 64 | #> 7 7a2a document log data 1 65 | #> 8 943c add helpfiles 10 66 | #> 9 917e update infrastructur 3 67 | #> 10 4fc0 remove garbage 6 68 | #> # ... with 139 more rows 69 | ``` 70 | 71 | Since we used `parse_log_detailed()`, there is detailed file-specific 72 | information available for every commit: 73 | 74 | ``` r 75 | tbl$nested[[3]] 76 | #> # A tibble: 3 x 5 77 | #> changed_file edits insertions deletions is_exact 78 | #> 79 | #> 1 DESCRIPTION 6 5 1 T 80 | #> 2 NAMESPACE 3 2 1 T 81 | #> 3 R/get_log.R 19 11 8 T 82 | ``` 83 | 84 | Since the data has such a high resolution, various graphs, tables etc. 85 | can be produced from it to provide insights into the git history. 86 | 87 | # Examples 88 | 89 | Since the output of `git_log_detailed()` is a nested tibble, you can 90 | work on it as you work on any other tibble. Let us first have a look at 91 | who comitted to this repository: 92 | 93 | ``` r 94 | log <- parse_log_detailed() 95 | log %>% 96 | group_by(author_name) %>% 97 | summarize(n = n()) 98 | #> # A tibble: 3 x 2 99 | #> author_name n 100 | #> 101 | #> 1 Jon Calder 2 102 | #> 2 jonmcalder 6 103 | #> 3 Lorenz Walthert 141 104 | ``` 105 | 106 | We can also investigate how the number of lines of each file in the R 107 | directory evolved. For that, we probaly want to view files with changed 108 | names as one file. Also, we probably don’t want to see boring plots for 109 | files that got changed only a few times. Let’s focus on files that were 110 | changed in at least five commits. 111 | 112 | ``` r 113 | lines <- log %>% 114 | unnest_log() %>% 115 | set_changed_file_to_latest_name() %>% 116 | add_line_history() 117 | #> The following name changes were identified (11 in total): 118 | #> ● man/{get_log.Rd => get_log_simple.Rd} 119 | #> ● man/{parse_log.Rd => parse_log_one.Rd} 120 | #> ● man/{get_pattern.Rd => get_pattern_multiple.Rd} 121 | #> ● man/{get_log_regex.Rd => git_log_detailed.Rd} 122 | #> ● man/{rmd_simple.Rd => git_report.Rd} 123 | #> ● R/{gitsum.R => gitsum-package.R} 124 | #> ● man/{git_log_detailed.Rd => parse_log_detailed.Rd} 125 | #> ● man/{git_log_simple.Rd => parse_log_simple.Rd} 126 | #> ● man/{ensure_gitusm_repo.Rd => ensure_gitsum_repo.Rd} 127 | #> ● man/{log.Rd => gitsumlog.Rd} 128 | #> ● man/{git_report.Rd => report_git.Rd} 129 | 130 | r_files <- grep("^R/", lines$changed_file, value = TRUE) 131 | 132 | to_plot <- lines %>% 133 | filter(changed_file %in% r_files) %>% 134 | add_n_times_changed_file() %>% 135 | filter(n_times_changed_file >= 10) 136 | ggplot(to_plot, aes(x = date, y = current_lines)) + 137 | geom_step() + 138 | scale_y_continuous(name = "Number of Lines", limits = c(0, NA)) + 139 | facet_wrap(~changed_file, scales = "free_y") 140 | ``` 141 | 142 | ![](README-per_file-1.png) 143 | 144 | Next, we want to see which files were contained in most commits: 145 | 146 | ``` r 147 | log %>% 148 | unnest_log() %>% 149 | mutate(changed_file = fct_lump(fct_infreq(changed_file), n = 10)) %>% 150 | filter(changed_file != "Other") %>% 151 | ggplot(aes(x = changed_file)) + geom_bar() + coord_flip() + 152 | theme_minimal() 153 | ``` 154 | 155 | ![](README-ggplot1-1.png) 156 | 157 | We can also easily get a visual overview of the number of insertions & 158 | deletions in commits over time: 159 | 160 | ``` r 161 | commit.dat <- data.frame( 162 | edits = rep(c("Insertions", "Deletions"), each = nrow(log)), 163 | commit = rep(1:nrow(log), 2), 164 | count = c(log$total_insertions, -log$total_deletions)) 165 | 166 | ggplot(commit.dat, aes(x = commit, y = count, fill = edits)) + 167 | geom_bar(stat = "identity", position = "identity") + 168 | theme_minimal() 169 | ``` 170 | 171 | ![](README-ggplot2-1.png) 172 | 173 | Or the number of commits broken down by day of the week: 174 | 175 | ``` r 176 | log %>% 177 | mutate(weekday = factor(weekday, c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"))) %>% 178 | ggplot(aes(x = weekday)) + geom_bar() + 179 | theme_minimal() 180 | ``` 181 | 182 | ![](README-ggplot3-1.png) 183 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | reference: 2 | - title: Parse and summarize a git repo 3 | desc: 4 | contents: 5 | - parse_log_detailed 6 | - parse_log_simple 7 | - report_git 8 | 9 | template: 10 | params: 11 | bootswatch: cerulean 12 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # DO NOT CHANGE the "init" and "install" sections below 2 | 3 | # Download script file from GitHub 4 | init: 5 | ps: | 6 | $ErrorActionPreference = "Stop" 7 | Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" 8 | Import-Module '..\appveyor-tool.ps1' 9 | 10 | install: 11 | ps: Bootstrap 12 | 13 | cache: 14 | - C:\RLibrary 15 | 16 | # Adapt as necessary starting from here 17 | 18 | build_script: 19 | - travis-tool.sh install_deps 20 | 21 | test_script: 22 | - travis-tool.sh run_tests 23 | 24 | on_failure: 25 | - 7z a failure.zip *.Rcheck\* 26 | - appveyor PushArtifact failure.zip 27 | 28 | artifacts: 29 | - path: '*.Rcheck\**\*.log' 30 | name: Logs 31 | 32 | - path: '*.Rcheck\**\*.out' 33 | name: Logs 34 | 35 | - path: '*.Rcheck\**\*.fail' 36 | name: Logs 37 | 38 | - path: '*.Rcheck\**\*.Rout' 39 | name: Logs 40 | 41 | - path: '\*_*.tar.gz' 42 | name: Bits 43 | 44 | - path: '\*_*.zip' 45 | name: Bits 46 | -------------------------------------------------------------------------------- /benchmarking/alternatives: -------------------------------------------------------------------------------- 1 | Alternatives 2 | 3 | * don't split into commit pieces first 4 | * use one grepl call per piece, not one per piece per extraction target 5 | * combine log_simple and get_log_regex() (simple is 6x faster) 6 | * each field needs to be own pattern anyways 7 | -------------------------------------------------------------------------------- /benchmarking/at_86acd.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/benchmarking/at_86acd.rds -------------------------------------------------------------------------------- /benchmarking/at_86acd_dplyr.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/benchmarking/at_86acd_dplyr.rds -------------------------------------------------------------------------------- /benchmarking/at_86acd_dplyr_parse_one2.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/benchmarking/at_86acd_dplyr_parse_one2.rds -------------------------------------------------------------------------------- /benchmarking/at_86acd_dplyr_parse_one2_extract_multiple.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/benchmarking/at_86acd_dplyr_parse_one2_extract_multiple.rds -------------------------------------------------------------------------------- /benchmarking/get_log_benchmarking.R: -------------------------------------------------------------------------------- 1 | library("microbenchmark") 2 | bench <- microbenchmark(read_only = get_log_regex(file_name = "tests/testthat/test_logs/.log_refactor.txt"), 3 | write_and_read = get_log_regex(path = "../refactor"), 4 | times = 10, unit = "s") 5 | 6 | 7 | microbenchmark(stringr = str_match("Date: Sat May 20 22:33:30 2017 +0200", "^Date:\\s{3}(\\w+)\\s"), 8 | stringr_full = str_match("Date: Sat May 20 22:33:30 2017 +0200", "^Date\\:\\s*(\\w+)\\s\\w+\\s+\\d+\\s\\d+:\\d+:\\d+\\s\\d+\\s.*"), 9 | base_r = gsub("^Date\\:\\s*(\\w+)\\s\\w+\\s+\\d+\\s\\d+:\\d+:\\d+\\s\\d+\\s.*", "\\1", "Date: Sat May 20 22:33:30 2017 +0200"), 10 | times = 100, unit = "ms") 11 | 12 | 13 | write_rds(bench, "benchmarking/at_86acd_dplyr_parse_one2_extract_multiple.rds") 14 | -------------------------------------------------------------------------------- /benchmarking/primer.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Benchmarking" 3 | author: "Lorenz Walthert" 4 | date: "5/20/2017" 5 | output: html_document 6 | --- 7 | 8 | This report gives an overview of the performance on the refactor repo at commit 9 | `86acd4d319a755e0a05593f400ba636363630eba`. 10 | ```{r} 11 | library("tidyverse") 12 | read_rds("../benchmarking/at_86acd") 13 | ``` 14 | Before any optimization, the mean was about 0.8 for read and 0.9 for read and 15 | write. 16 | Changing the approach and use dplyr instead of nested lapplyr and some other 17 | modifications slightly slows down the performance. However, there is now a 18 | progress bar. 19 | ```{r} 20 | read_rds("../benchmarking/at_86acd") 21 | ``` 22 | 23 | Also, it was possible to use `stringr` for matching 24 | ```{r} 25 | read_rds("../benchmarking/at_86acd_dplyr_parse_one2.rds") 26 | ``` 27 | 28 | Further more, multipel strings were matched with one regex call 29 | ```{r} 30 | read_rds("../benchmarking/at_86acd_dplyr_parse_one2_extract_multiple.rds") 31 | ``` 32 | 33 | -------------------------------------------------------------------------------- /data/gitsumlog.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/data/gitsumlog.rda -------------------------------------------------------------------------------- /docs/LICENSE.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | License • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
41 |
42 | 71 | 72 | 73 |
74 | 75 |
76 |
77 | 80 | 81 |
MIT License
 82 | 
 83 | Copyright (c) 2017 Lorenz Walthert
 84 | 
 85 | Permission is hereby granted, free of charge, to any person obtaining a copy
 86 | of this software and associated documentation files (the "Software"), to deal
 87 | in the Software without restriction, including without limitation the rights
 88 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 89 | copies of the Software, and to permit persons to whom the Software is
 90 | furnished to do so, subject to the following conditions:
 91 | 
 92 | The above copyright notice and this permission notice shall be included in all
 93 | copies or substantial portions of the Software.
 94 | 
 95 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 96 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 97 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 98 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 99 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
100 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
101 | SOFTWARE.
102 | 
103 | 104 |
105 | 106 |
107 | 108 | 109 |
110 | 113 | 114 |
115 |

Site built with pkgdown.

116 |
117 | 118 |
119 |
120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /docs/README-ggplot1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/docs/README-ggplot1-1.png -------------------------------------------------------------------------------- /docs/README-ggplot2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/docs/README-ggplot2-1.png -------------------------------------------------------------------------------- /docs/README-ggplot3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/docs/README-ggplot3-1.png -------------------------------------------------------------------------------- /docs/README-per_file-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/docs/README-per_file-1.png -------------------------------------------------------------------------------- /docs/articles/cached-logs_files/figure-html/unnamed-chunk-1-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/docs/articles/cached-logs_files/figure-html/unnamed-chunk-1-1.png -------------------------------------------------------------------------------- /docs/articles/cached-logs_files/figure-html/unnamed-chunk-1-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/docs/articles/cached-logs_files/figure-html/unnamed-chunk-1-2.png -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Articles • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
41 |
42 | 83 | 84 | 85 |
86 | 87 | 90 | 91 |
92 |
93 |
94 |

All vignettes

95 |

96 | 97 | 100 |
101 |
102 |
103 | 104 |
105 | 108 | 109 |
110 |

Site built with pkgdown.

111 |
112 | 113 |
114 |
115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Authors • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
41 |
42 | 71 | 72 | 73 |
74 | 75 |
76 |
77 | 80 | 81 |
    82 |
  • 83 |

    Lorenz Walthert. Author, maintainer. 84 |

    85 |
  • 86 |
87 | 88 |
89 | 90 |
91 | 92 | 93 |
94 | 97 | 98 |
99 |

Site built with pkgdown.

100 |
101 | 102 |
103 |
104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /docs/jquery.sticky-kit.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 3 | */ 4 | (function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k)); 5 | if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("
"))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q, 6 | u=a.outerHeight(!0),r=a.css("float"),h&&h.css({width:a.outerWidth(!0),height:u,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),e))return l()};x();if(u!==C)return D=void 0,c=q,z=E,l=function(){var b,l,e,k;if(!G&&(e=!1,null!=z&&(--z,0>=z&&(z=E,x(),e=!0)),e||A.height()===I||x(),e=f.scrollTop(),null!=D&&(l=e-D),D=e,m?(w&&(k=e+u+c>C+n,v&&!k&&(v=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),eb&&!v&&(c-=l,c=Math.max(b-u,c),c=Math.min(q,c),m&&a.css({top:c+"px"})))):e>F&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(t),null==p&&(a.after(h),"left"!==r&&"right"!==r||h.append(a)),a.trigger("sticky_kit:stick")),m&&w&&(null==k&&(k=e+u+c>C+n),!v&&k)))return v=!0,"static"===g.css("position")&&g.css({position:"relative"}), 8 | a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize", 9 | y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/pkgdown.css: -------------------------------------------------------------------------------- 1 | /* Sticker footer */ 2 | body > .container { 3 | display: flex; 4 | padding-top: 60px; 5 | min-height: calc(100vh); 6 | flex-direction: column; 7 | } 8 | 9 | body > .container .row { 10 | flex: 1; 11 | } 12 | 13 | footer { 14 | margin-top: 45px; 15 | padding: 35px 0 36px; 16 | border-top: 1px solid #e5e5e5; 17 | color: #666; 18 | display: flex; 19 | } 20 | footer p { 21 | margin-bottom: 0; 22 | } 23 | footer div { 24 | flex: 1; 25 | } 26 | footer .pkgdown { 27 | text-align: right; 28 | } 29 | footer p { 30 | margin-bottom: 0; 31 | } 32 | 33 | img.icon { 34 | float: right; 35 | } 36 | 37 | img { 38 | max-width: 100%; 39 | } 40 | 41 | /* Section anchors ---------------------------------*/ 42 | 43 | a.anchor { 44 | margin-left: -30px; 45 | display:inline-block; 46 | width: 30px; 47 | height: 30px; 48 | visibility: hidden; 49 | 50 | background-image: url(./link.svg); 51 | background-repeat: no-repeat; 52 | background-size: 20px 20px; 53 | background-position: center center; 54 | } 55 | 56 | .hasAnchor:hover a.anchor { 57 | visibility: visible; 58 | } 59 | 60 | @media (max-width: 767px) { 61 | .hasAnchor:hover a.anchor { 62 | visibility: hidden; 63 | } 64 | } 65 | 66 | 67 | /* Fixes for fixed navbar --------------------------*/ 68 | 69 | .contents h1, .contents h2, .contents h3, .contents h4 { 70 | padding-top: 60px; 71 | margin-top: -60px; 72 | } 73 | 74 | /* Static header placement on mobile devices */ 75 | @media (max-width: 767px) { 76 | .navbar-fixed-top { 77 | position: absolute; 78 | } 79 | .navbar { 80 | padding: 0; 81 | } 82 | } 83 | 84 | 85 | /* Sidebar --------------------------*/ 86 | 87 | #sidebar { 88 | margin-top: 30px; 89 | } 90 | #sidebar h2 { 91 | font-size: 1.5em; 92 | margin-top: 1em; 93 | } 94 | 95 | #sidebar h2:first-child { 96 | margin-top: 0; 97 | } 98 | 99 | #sidebar .list-unstyled li { 100 | margin-bottom: 0.5em; 101 | } 102 | 103 | /* Reference index & topics ----------------------------------------------- */ 104 | 105 | .ref-index th {font-weight: normal;} 106 | .ref-index h2 {font-size: 20px;} 107 | 108 | .ref-index td {vertical-align: top;} 109 | .ref-index .alias {width: 40%;} 110 | .ref-index .title {width: 60%;} 111 | 112 | .ref-index .alias {width: 40%;} 113 | .ref-index .title {width: 60%;} 114 | 115 | .ref-arguments th {text-align: right; padding-right: 10px;} 116 | .ref-arguments th, .ref-arguments td {vertical-align: top;} 117 | .ref-arguments .name {width: 20%;} 118 | .ref-arguments .desc {width: 80%;} 119 | 120 | /* Nice scrolling for wide elements --------------------------------------- */ 121 | 122 | table { 123 | display: block; 124 | overflow: auto; 125 | } 126 | 127 | /* Syntax highlighting ---------------------------------------------------- */ 128 | 129 | pre { 130 | word-wrap: normal; 131 | word-break: normal; 132 | border: 1px solid #eee; 133 | } 134 | 135 | pre, code { 136 | background-color: #f8f8f8; 137 | color: #333; 138 | } 139 | 140 | pre .img { 141 | margin: 5px 0; 142 | } 143 | 144 | pre .img img { 145 | background-color: #fff; 146 | display: block; 147 | height: auto; 148 | } 149 | 150 | code a, pre a { 151 | color: #375f84; 152 | } 153 | 154 | .fl {color: #1514b5;} 155 | .fu {color: #000000;} /* function */ 156 | .ch,.st {color: #036a07;} /* string */ 157 | .kw {color: #264D66;} /* keyword */ 158 | .co {color: #888888;} /* comment */ 159 | 160 | .message { color: black; font-weight: bolder;} 161 | .error { color: orange; font-weight: bolder;} 162 | .warning { color: #6A0366; font-weight: bolder;} 163 | 164 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | $("#sidebar").stick_in_parent({offset_top: 40}); 3 | $('body').scrollspy({ 4 | target: '#sidebar', 5 | offset: 60 6 | }); 7 | 8 | var cur_path = paths(location.pathname); 9 | $("#navbar ul li a").each(function(index, value) { 10 | if (value.text == "Home") 11 | return; 12 | if (value.getAttribute("href") === "#") 13 | return; 14 | 15 | var path = paths(value.pathname); 16 | if (is_prefix(cur_path, path)) { 17 | // Add class to parent
  • , and enclosing
  • if in dropdown 18 | var menu_anchor = $(value); 19 | menu_anchor.parent().addClass("active"); 20 | menu_anchor.closest("li.dropdown").addClass("active"); 21 | } 22 | }); 23 | }); 24 | 25 | function paths(pathname) { 26 | var pieces = pathname.split("/"); 27 | pieces.shift(); // always starts with / 28 | 29 | var end = pieces[pieces.length - 1]; 30 | if (end === "index.html" || end === "") 31 | pieces.pop(); 32 | return(pieces); 33 | } 34 | 35 | function is_prefix(needle, haystack) { 36 | if (needle.length > haystack.lengh) 37 | return(false); 38 | 39 | for (var i = 0; i < haystack.length; i++) { 40 | if (needle[i] != haystack[i]) 41 | return(false); 42 | } 43 | 44 | return(true); 45 | } 46 | -------------------------------------------------------------------------------- /docs/reference/add_line_history.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Add line history — add_line_history • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    Add amount of lines added by commits (insertions - deletions) plus number of 83 | total lines a file has according to past insertions and deletions 84 | (via base::cumsum().

    85 | 86 | 87 |
    add_line_history(log)
    88 | 89 |

    Arguments

    90 | 91 | 92 | 93 | 94 | 95 | 96 |
    log

    An nested gitsum log, for example obtained through parse_log_detailed().

    97 | 98 | 99 |
    100 | 107 |
    108 | 109 |
    110 | 113 | 114 |
    115 |

    Site built with pkgdown.

    116 |
    117 | 118 |
    119 |
    120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /docs/reference/check_overwriting_clearance.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Check whether a file / path exists and return an error when it cannot be 10 | overwritten. — check_overwriting_clearance • gitsum 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 36 | 37 | 38 | 39 | 40 | 41 |
    42 |
    43 | 72 | 73 | 74 |
    75 | 76 |
    77 |
    78 | 82 | 83 | 84 |

    Check whether a file / path exists and return an error when it cannot be 85 | overwritten.

    86 | 87 | 88 |
    check_overwriting_clearance(path, over_write, fun = file.exists)
    89 | 90 |

    Arguments

    91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 101 | 102 | 103 | 104 | 106 | 107 |
    path

    The path to the root directory of the gitsum repository.

    over_write

    Whether or not existing files / directories should be 100 | overwritten.

    fun

    The function to apply to the path, either file.exists, or 105 | dir.exists.

    108 | 109 | 110 |
    111 | 118 |
    119 | 120 |
    121 | 124 | 125 |
    126 |

    Site built with pkgdown.

    127 |
    128 | 129 |
    130 |
    131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /docs/reference/dump_parsed_log.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Dump a parsed log into .gitsum — dump_parsed_log • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    Store a parsed git log in a gitsum repository.

    83 | 84 | 85 |
    dump_parsed_log(log, path = ".", over_write = FALSE, verbose = TRUE)
     86 | 
     87 | dump_last_commit(log, path, verbose = TRUE)
    88 | 89 |

    Arguments

    90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 104 | 105 | 106 | 107 | 108 | 109 |
    log

    A parsed log as a tibble

    path

    The path to the root directory of the gitsum repository.

    over_write

    Whether or not existing files / directories should be 103 | overwritten.

    verbose

    Whether or not to send informative messages to the console.

    110 | 111 |

    Functions

    112 | 113 |
      114 |
    • dump_last_commit: Dumps the last commit into .gitsum

    • 115 |
    116 | 117 | 118 |
    119 | 128 |
    129 | 130 |
    131 | 134 | 135 |
    136 |

    Site built with pkgdown.

    137 |
    138 | 139 |
    140 |
    141 | 142 | 143 | 144 | -------------------------------------------------------------------------------- /docs/reference/ensure_gitsum_repo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Make sure the repository is a gitsum repository and create one if it is not — ensure_gitsum_repo • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    Make sure the repository is a gitsum repository and create one if it is not

    83 | 84 | 85 |
    ensure_gitsum_repo(path = ".")
    86 | 87 |

    Arguments

    88 | 89 | 90 | 91 | 92 | 93 | 94 |
    path

    The path to the root directory of the gitsum repository.

    95 | 96 | 97 |
    98 | 105 |
    106 | 107 |
    108 | 111 | 112 |
    113 |

    Site built with pkgdown.

    114 |
    115 | 116 |
    117 |
    118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /docs/reference/extract_factory_multiple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | closure to extract multiple regex pattern from vector — extract_factory_multiple • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    closure to extract multiple regex pattern from vector

    83 | 84 | 85 |
    extract_factory_multiple(pattern)
    86 | 87 |

    Arguments

    88 | 89 | 90 | 91 | 92 | 93 | 94 |
    pattern

    The pattern the function should be able to extract.

    95 | 96 | 97 |
    98 | 105 |
    106 | 107 |
    108 | 111 | 112 |
    113 |

    Site built with pkgdown.

    114 |
    115 | 116 |
    117 |
    118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /docs/reference/find_message_and_desc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | extract message or description from a log — find_message_and_desc • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    For message and description extraction, a different approach is used and 83 | one cannot rely on the approach with the simple extraction factory.

    84 | 85 | 86 |
    find_message_and_desc(raw, target)
    87 | 88 |

    Arguments

    89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 |
    raw

    A character vector corresponding to one commit.

    target

    either "message" or "description

    100 | 101 | 102 |
    103 | 110 |
    111 | 112 |
    113 | 116 | 117 |
    118 |

    Site built with pkgdown.

    119 |
    120 | 121 |
    122 |
    123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /docs/reference/get_pattern_multiple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | regex patterns for extraction — get_pattern_multiple • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    regex patterns for extraction

    83 | 84 | 85 |
    get_pattern_multiple()
    86 | 87 |

    Value

    88 | 89 |

    returns a named vector with regex patterns to extract from a 90 | git log.

    91 | 92 | 93 |
    94 | 102 |
    103 | 104 |
    105 | 108 | 109 |
    110 |

    Site built with pkgdown.

    111 |
    112 | 113 |
    114 |
    115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /docs/reference/get_raw_log.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Obtain the log raw data — get_raw_log • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    Obtain the log raw data

    83 | 84 | 85 |
    get_raw_log(path, file_name = NULL, remove = is.null(file_name),
     86 |   commit_range = NULL)
    87 | 88 |

    Arguments

    89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 108 | 109 |
    path

    The path to the git directory one wants to create summaries for.

    file_name

    The name of the temporary file. If NULL, a file is 98 | created, otherwise, a file is read.

    remove

    Whether a log should be deleted after read in.

    commit_range

    A string of the form "hash1..hash2" indicating the commit 107 | range to parse. NULL means all commits.

    110 | 111 | 112 |
    113 | 120 |
    121 | 122 |
    123 | 126 | 127 |
    128 |

    Site built with pkgdown.

    129 |
    130 | 131 |
    132 |
    133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /docs/reference/gitsum.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Parse and summarize a git repository — gitsum • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    gitsum provides tools to parse a git repository history and 83 | can create automated markdown reports from the parsed history.

    84 | 85 | 86 | 87 | 88 |
    89 | 99 |
    100 | 101 |
    102 | 105 | 106 |
    107 |

    Site built with pkgdown.

    108 |
    109 | 110 |
    111 |
    112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /docs/reference/gitsumlog.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Sample log data from git repository — gitsumlog • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    Sample log data from git repository

    83 | 84 | 85 | 86 | 87 |
    88 | 98 |
    99 | 100 |
    101 | 104 | 105 |
    106 |

    Site built with pkgdown.

    107 |
    108 | 109 |
    110 |
    111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /docs/reference/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Function reference • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 83 | 84 |
    85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 98 | 99 | 100 | 101 | 104 | 105 | 106 | 107 | 110 | 111 | 112 | 113 | 116 | 117 | 118 | 119 |
    95 |

    Parse and summarize a git repo

    96 |

    97 |
    102 |

    parse_log_detailed parse_log_detailed_full_run

    103 |

    Obtain a detailed git log

    108 |

    parse_log_simple

    109 |

    Obtain a simple log for a git repo

    114 |

    report_git

    115 |

    Create a summary report of a git repository

    120 |
    121 |
    122 | 123 | 129 |
    130 | 131 |
    132 | 135 | 136 |
    137 |

    Site built with pkgdown.

    138 |
    139 | 140 |
    141 |
    142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /docs/reference/log.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Sample log data from git repository — log • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 83 | 84 | 85 |
    86 | 87 |
    88 |
    89 | 92 | 93 | 94 |

    Sample log data from git repository

    95 | 96 | 97 | 98 | 99 |
    100 | 110 |
    111 | 112 |
    113 | 116 | 117 |
    118 |

    Site built with pkgdown.

    119 |
    120 | 121 |
    122 |
    123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /docs/reference/manage_gitsum.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Manage a gitsum repository — manage_gitsum • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    A gitsum repository is a git repository with an additional .gitsum folder in 83 | the root directory that is mainly used to store a parsed git log as a tibble.

    84 | 85 | 86 |
    init_gitsum(path = ".", over_write = FALSE)
     87 | 
     88 | remove_gitsum(path = ".")
    89 | 90 |

    Arguments

    91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 |
    path

    The path to the repository to initialize.

    over_write

    Whether or not an existing directory should be overwritten.

    102 | 103 |

    Functions

    104 | 105 |
      106 |
    • init_gitsum: Calling this function will parse the available git 107 | history and dump it into the directory .gitsum.

    • 108 |
    • remove_gitsum: Removes the gitsum repository, i.e just the folder 109 | .gitsum and its contents.

    • 110 |
    111 | 112 | 113 |
    114 | 123 |
    124 | 125 |
    126 | 129 | 130 |
    131 |

    Site built with pkgdown.

    132 |
    133 | 134 |
    135 |
    136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /docs/reference/parse_log_one.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | parse a raw log — parse_log_one • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    parse a raw log

    83 | 84 | 85 |
    parse_log_one(raw, fnc_list, has_merge)
    86 | 87 |

    Arguments

    88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 98 | 99 | 100 | 101 | 103 | 104 |
    raw

    a character vector corresponding to one commit.

    fnc_list

    the list list of named functions that return the elements 97 | we want to extract from the log, i.e. author, hash etc.

    has_merge

    Whether or not raw is a merge commit. This is relevant 102 | because merge commits have additional lines.

    105 | 106 | 107 |
    108 | 115 |
    116 | 117 |
    118 | 121 | 122 |
    123 |

    Site built with pkgdown.

    124 |
    125 | 126 |
    127 |
    128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /docs/reference/parse_log_simple.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Obtain a simple log for a git repo — parse_log_simple • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    This function returns a git log in a tabular format.

    83 | 84 | 85 |
    parse_log_simple(path = ".", file_name = NULL)
    86 | 87 |

    Arguments

    88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 98 | 99 |
    path

    The path to the git directory one wants to create summaries for.

    file_name

    The path to a raw log. If NULL, a raw log is created and 97 | read in and deleted after read-in, otherwise, an existing log is read.

    100 | 101 |

    See also

    102 | 103 |

    See parse_log_detailed for a slower alternative with more 104 | information.

    105 | 106 | 107 |
    108 | 117 |
    118 | 119 |
    120 | 123 | 124 |
    125 |

    Site built with pkgdown.

    126 |
    127 | 128 |
    129 |
    130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /docs/reference/read_gitsum.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Read gitsum data into R — read_gitsum • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    Read gitsum data into R

    83 | 84 | 85 |
    read_log(path = ".")
     86 | 
     87 | read_last_commit(path = ".")
     88 | 
     89 | read_last_hash(path = ".")
    90 | 91 |

    Arguments

    92 | 93 | 94 | 95 | 96 | 97 | 98 |
    path

    The path to the root directory of the gitsum repository.

    99 | 100 |

    Functions

    101 | 102 |
      103 |
    • read_log: Reads a parsed log.

    • 104 |
    • read_last_commit: Reads the last parsed commit.

    • 105 |
    • read_last_hash: Reads the last parsed hash.

    • 106 |
    107 | 108 | 109 |
    110 | 119 |
    120 | 121 |
    122 | 125 | 126 |
    127 |

    Site built with pkgdown.

    128 |
    129 | 130 |
    131 |
    132 | 133 | 134 | 135 | -------------------------------------------------------------------------------- /docs/reference/testthat_file.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Create the path to a test that file — testthat_file • gitsum 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 39 | 40 |
    41 |
    42 | 71 | 72 | 73 |
    74 | 75 |
    76 |
    77 | 80 | 81 | 82 |

    Create the path to a test that file

    83 | 84 | 85 |
    testthat_file(...)
    86 | 87 |

    Arguments

    88 | 89 | 90 | 91 | 92 | 94 | 95 |
    ...

    Arguments passed to file.path() to construct the path after 93 | ".../tests/testthat/"

    96 | 97 | 98 |
    99 | 106 |
    107 | 108 |
    109 | 112 | 113 |
    114 |

    Site built with pkgdown.

    115 |
    116 | 117 |
    118 |
    119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /gitsum.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace,vignette 22 | -------------------------------------------------------------------------------- /index.Rmd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | *Package is work in progress\! If you encounter errors / problems, 5 | please file an issue or make a 6 | PR.* 7 | 8 | [![stability-unstable](https://img.shields.io/badge/stability-unstable-yellow.svg)](https://github.com/joethorley/stability-badges#unstable) 9 | [![codecov](https://codecov.io/gh/lorenzwalthert/gitsum/branch/master/graph/badge.svg)](https://codecov.io/gh/lorenzwalthert/gitsum) 10 | [![Build 11 | Status](https://travis-ci.org/lorenzwalthert/gitsum.svg?branch=master)](https://travis-ci.org/lorenzwalthert/gitsum) 12 | [![AppVeyor Build 13 | Status](https://ci.appveyor.com/api/projects/status/github/lorenzwalthert/gitsum?branch=master&svg=true)](https://ci.appveyor.com/project/lorenzwalthert/gitsum) 14 | 15 | # Introduction 16 | 17 | This package parses a git repository history to collect comprehensive 18 | information about the activity in the repo. The parsed data is made 19 | available to the user in a tabular format. The package can also generate 20 | reports based on the parse data. 21 | 22 | There are two main functions for parsing the history, both return 23 | tabular data: 24 | 25 | - `parse_log_simple()` is a relatively fast parser and returns a 26 | tibble with one commit per row. There is no file-specific 27 | information. 28 | - `parse_log_detailed()` outputs a nested tibble and for each commit, 29 | the names of the amended files, number of lines changed ect. 30 | available. This function is slower. 31 | 32 | `report_git()` creates a html, pdf, or word report with the parsed log 33 | data according to a template. Templates can be created by the user or a 34 | template from the `gitsum` package can be used. 35 | 36 | Let’s see the package in action. 37 | 38 | ``` r 39 | library("gitsum") 40 | library("tidyverse") 41 | library("forcats") 42 | ``` 43 | 44 | We can obtain a parsed log like this: 45 | 46 | ``` r 47 | tbl <- parse_log_detailed() %>% 48 | arrange(date) %>% 49 | select(short_hash, short_message, total_files_changed, nested) 50 | tbl 51 | #> # A tibble: 101 x 4 52 | #> short_hash short_message total_files_changed nested 53 | #> 54 | #> 1 243f initial commit 7 55 | #> 2 f8ee add log example data 1 56 | #> 3 6328 add parents 3 57 | #> 4 dfab intermediate 1 58 | #> 5 7825 add licence 1 59 | #> 6 2ac3 add readme 2 60 | #> 7 7a2a document log data 1 61 | #> 8 943c add helpfiles 10 62 | #> 9 917e update infrastructur 3 63 | #> 10 4fc0 remove garbage 6 64 | #> # ... with 91 more rows 65 | ``` 66 | 67 | Since we used `parse_log_detailed()`, there is detailed file-specific 68 | information available for every commit: 69 | 70 | ``` r 71 | tbl$nested[[3]] 72 | #> # A tibble: 3 x 5 73 | #> changed_file edits insertions deletions is_exact 74 | #> 75 | #> 1 DESCRIPTION 6 5 1 TRUE 76 | #> 2 NAMESPACE 3 2 1 TRUE 77 | #> 3 R/get_log.R 19 11 8 TRUE 78 | ``` 79 | 80 | Since the data has such a high resolution, various graphs, tables etc. 81 | can be produced from it to provide insights into the git history. 82 | 83 | # Examples 84 | 85 | Since the output of `git_log_detailed()` is a nested tibble, you can 86 | work on it as you work on any other tibble. Let us first have a look at 87 | who comitted to this repository: 88 | 89 | ``` r 90 | log <- parse_log_detailed() 91 | log %>% 92 | group_by(author_name) %>% 93 | summarize(n = n()) 94 | #> # A tibble: 3 x 2 95 | #> author_name n 96 | #> 97 | #> 1 Jon Calder 2 98 | #> 2 jonmcalder 6 99 | #> 3 Lorenz Walthert 93 100 | ``` 101 | 102 | We can also investigate how the number of lines of each file in the R 103 | directory evolved. 104 | 105 | ``` r 106 | lines <- log %>% 107 | unnest() %>% 108 | add_line_history() 109 | 110 | r_files <- grep("^R/", lines$changed_file, value = TRUE) 111 | 112 | to_plot <- lines %>% 113 | filter(changed_file %in% r_files) 114 | ggplot(to_plot, aes(x = date, y = current_lines)) + 115 | geom_step() + 116 | scale_y_continuous(name = "Number of Lines", limits = c(0, NA)) + 117 | facet_wrap(~changed_file, scales = "free_y") 118 | ``` 119 | 120 | ![](README-per_file-1.png) 121 | 122 | Next, we want to see which files were contained in most commits: 123 | 124 | ``` r 125 | log %>% 126 | unnest(nested) %>% # unnest the tibble 127 | mutate(changed_file = fct_lump(fct_infreq(changed_file), n = 10)) %>% 128 | filter(changed_file != "Other") %>% 129 | ggplot(aes(x = changed_file)) + geom_bar() + coord_flip() + 130 | theme_minimal() 131 | ``` 132 | 133 | ![](README-ggplot1-1.png) 134 | 135 | We can also easily get a visual overview of the number of insertions & 136 | deletions in commits over time: 137 | 138 | ``` r 139 | commit.dat <- data.frame( 140 | edits = rep(c("Insertions", "Deletions"), each = nrow(log)), 141 | commit = rep(1:nrow(log), 2), 142 | count = c(log$total_insertions, -log$total_deletions)) 143 | 144 | ggplot(commit.dat, aes(x = commit, y = count, fill = edits)) + 145 | geom_bar(stat = "identity", position = "identity") + 146 | theme_minimal() 147 | ``` 148 | 149 | ![](README-ggplot2-1.png) 150 | 151 | Or the number of commits broken down by day of the week: 152 | 153 | ``` r 154 | log %>% 155 | mutate(weekday = factor(weekday, c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"))) %>% 156 | ggplot(aes(x = weekday)) + geom_bar() + 157 | theme_minimal() 158 | ``` 159 | 160 | ![](README-ggplot3-1.png) 161 | -------------------------------------------------------------------------------- /inst/report_templates/repo_summary_simple.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Repo Summary Simple" 3 | output: 4 | word_document: default 5 | pdf_document: default 6 | html_document: default 7 | params: 8 | log:placeholder 9 | --- 10 | 11 | ```{r setup, include=FALSE} 12 | knitr::opts_chunk$set(echo = TRUE) 13 | library("magrittr") 14 | library("dplyr") 15 | library("tibble") 16 | library("ggplot2") 17 | library("tidyr") 18 | library("forcats") 19 | ``` 20 | Let us first have a look at who comitted to this repository: 21 | ```{r} 22 | log %>% 23 | group_by(author_name) %>% 24 | count() %>% 25 | arrange(desc(n)) 26 | ``` 27 | 28 | Next, we want to see which files were contained in most commits: 29 | ```{r ggplot1} 30 | log %>% 31 | unnest(nested) %>% # unnest the tibble 32 | mutate(changed_file = fct_infreq(fct_lump(changed_file, n = 10))) %>% 33 | filter(changed_file != "Other") %>% 34 | ggplot(aes(x = changed_file)) + geom_bar() + coord_flip() + 35 | theme_minimal() 36 | ``` 37 | 38 | We can also easily get a visual overview of the number of insertions & deletions in commits over time: 39 | ```{r ggplot2} 40 | commit.dat <- data.frame( 41 | edits = rep(c("Insertions", "Deletions"), each = nrow(log)), 42 | commit = rep(1:nrow(log), 2), 43 | count = c(log$total_insertions, -log$total_deletions)) 44 | 45 | ggplot(commit.dat, aes(x = commit, y = count, fill = edits)) + 46 | geom_bar(stat = "identity", position = "identity") + 47 | theme_minimal() 48 | ``` 49 | 50 | Or the number of commits broken down by day of the week: 51 | ```{r ggplot3} 52 | log %>% 53 | mutate(weekday = factor(weekday, c("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"))) %>% 54 | ggplot(aes(x = weekday)) + geom_bar() + 55 | theme_minimal() 56 | ``` 57 | 58 | 59 | Or how the line number of the files in the directory R changed. 60 | ```{r} 61 | lines <- log %>% 62 | unnest() %>% 63 | add_line_history() 64 | 65 | r_files <- grep("^R/", lines$changed_file, value = TRUE) 66 | 67 | if (length(r_files) > 0) { 68 | to_plot <- lines %>% 69 | filter(changed_file %in% r_files) 70 | ggplot(to_plot, aes(x = date, y = current_lines)) + 71 | geom_step() + 72 | scale_y_continuous(name = "Number of Lines", limits = c(0, NA)) + 73 | facet_wrap(~changed_file, scales = "free_y") 74 | 75 | } else { 76 | print("No R/ directory found.") 77 | } 78 | ``` 79 | 80 | -------------------------------------------------------------------------------- /man/add_attributes_detailed.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/engineer-features-base.R 3 | \name{add_attributes_detailed} 4 | \alias{add_attributes_detailed} 5 | \title{Add base attributes to a log} 6 | \usage{ 7 | add_attributes_detailed(log) 8 | } 9 | \arguments{ 10 | \item{log}{An unnested log.} 11 | } 12 | \description{ 13 | Add base attributes to a log 14 | } 15 | \details{ 16 | Derives some attributes from the parsed raw log and converts them to the 17 | desired format. 18 | The following attributes merit special mentioning: 19 | \itemize{ 20 | \item commit_nr: The number of the commit in the repo. This can be used to sort 21 | commits (in contrast to the commit date) in chronological order, that is, 22 | in the oder in which they were committed. 23 | } 24 | } 25 | \keyword{internal} 26 | -------------------------------------------------------------------------------- /man/add_is_exact.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/engineer-features-base.R 3 | \name{add_is_exact} 4 | \alias{add_is_exact} 5 | \title{Is the information exact?} 6 | \usage{ 7 | add_is_exact(log) 8 | } 9 | \arguments{ 10 | \item{log}{An unnested log.} 11 | } 12 | \description{ 13 | Create a column indicating whether insertions and deletions are exact counts. 14 | } 15 | \keyword{internal} 16 | -------------------------------------------------------------------------------- /man/add_line_history.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/enrich.R 3 | \name{add_line_history} 4 | \alias{add_line_history} 5 | \title{Add line history} 6 | \usage{ 7 | add_line_history(log) 8 | } 9 | \arguments{ 10 | \item{log}{An unested gitsum log, for example obtained through 11 | \code{\link[=parse_log_detailed]{parse_log_detailed()}}.} 12 | } 13 | \description{ 14 | Add amount of lines added by each commits by file (insertions - deletions) 15 | plus number of total lines a file has according to past insertions and 16 | deletions (via \code{\link[base:cumsum]{base::cumsum()}}. 17 | } 18 | \examples{ 19 | add_line_history(tidyr::unnest(gitsumlog)) 20 | } 21 | -------------------------------------------------------------------------------- /man/add_n_times_changed_file.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/enrich.R 3 | \name{add_n_times_changed_file} 4 | \alias{add_n_times_changed_file} 5 | \title{How many times did file get changed?} 6 | \usage{ 7 | add_n_times_changed_file(log) 8 | } 9 | \arguments{ 10 | \item{log}{An unnested log.} 11 | } 12 | \description{ 13 | Add a variable \code{n_times_changed_file} to the unnested log, which contains 14 | the number of times a file was changed according to \code{log}. This may be 15 | helpful for subsetting. 16 | } 17 | -------------------------------------------------------------------------------- /man/check_overwriting_clearance.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/io.R 3 | \name{check_overwriting_clearance} 4 | \alias{check_overwriting_clearance} 5 | \title{Check whether a file / path exists and return an error when it cannot be 6 | overwritten.} 7 | \usage{ 8 | check_overwriting_clearance(path, over_write, fun = file.exists) 9 | } 10 | \arguments{ 11 | \item{path}{The path to the root directory of the gitsum repository.} 12 | 13 | \item{over_write}{Whether or not existing files / directories should be 14 | overwritten.} 15 | 16 | \item{fun}{The function to apply to the path, either file.exists, or 17 | dir.exists.} 18 | } 19 | \description{ 20 | Check whether a file / path exists and return an error when it cannot be 21 | overwritten. 22 | } 23 | \keyword{internal} 24 | -------------------------------------------------------------------------------- /man/combine_dir_and_base.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/renamed-files.R 3 | \name{combine_dir_and_base} 4 | \alias{combine_dir_and_base} 5 | \title{Derive full paths} 6 | \usage{ 7 | combine_dir_and_base(dirs, base_names, extensions, reassignment_index) 8 | } 9 | \arguments{ 10 | \item{dirs}{Character vector with directories.} 11 | 12 | \item{base_names}{List of pairs containing the old base name as the first 13 | element and the new base name as the second.} 14 | 15 | \item{extensions}{The extensions that indicate the suffix of the name.} 16 | 17 | \item{reassignment_index}{Integer vector indicating the position of the 18 | re-assignment in the original unnested detailed log.} 19 | } 20 | \description{ 21 | Derive full paths given directory paths, base_names, extensions and 22 | reassignment index. 23 | } 24 | \examples{ 25 | gitsum:::combine_dir_and_base( 26 | "R", 27 | list(c("a", "b"), c("API", "api2"), c("scr", "inst/include")), 28 | list("", "", "dplyr_types.h"), c(1, 42, 61) 29 | ) 30 | } 31 | \keyword{internal} 32 | -------------------------------------------------------------------------------- /man/combine_dir_and_base_one.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/renamed-files.R 3 | \name{combine_dir_and_base_one} 4 | \alias{combine_dir_and_base_one} 5 | \title{Combining paths} 6 | \usage{ 7 | combine_dir_and_base_one(dirname, base_name, extensions, 8 | reassignment_index) 9 | } 10 | \arguments{ 11 | \item{dirname}{A directory name.} 12 | 13 | \item{base_name}{The base name of a file.} 14 | 15 | \item{extensions}{The extensions that indicate the suffix of the name.} 16 | 17 | \item{reassignment_index}{Integer vector indicating the position of the 18 | re-assignment in the original unnested detailed log.} 19 | } 20 | \description{ 21 | Combine dir with old and new basename and extension 22 | } 23 | \keyword{internal} 24 | -------------------------------------------------------------------------------- /man/dump_parsed_log.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/io.R 3 | \name{dump_parsed_log} 4 | \alias{dump_parsed_log} 5 | \alias{dump_last_commit} 6 | \title{Dump a parsed log into .gitsum} 7 | \usage{ 8 | dump_parsed_log(log, path = ".", over_write = FALSE, verbose = TRUE) 9 | 10 | dump_last_commit(log, path, verbose = TRUE) 11 | } 12 | \arguments{ 13 | \item{log}{A parsed log as a tibble} 14 | 15 | \item{path}{The path to the root directory of the gitsum repository.} 16 | 17 | \item{over_write}{Whether or not existing files / directories should be 18 | overwritten.} 19 | 20 | \item{verbose}{Whether or not to send informative messages to the console.} 21 | } 22 | \description{ 23 | Store a parsed git log in a gitsum repository. 24 | } 25 | \section{Functions}{ 26 | \itemize{ 27 | \item \code{dump_last_commit}: Dumps the last commit into .gitsum 28 | }} 29 | 30 | \keyword{internal} 31 | -------------------------------------------------------------------------------- /man/ensure_enclosing.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/renamed-files.R 3 | \name{ensure_enclosing} 4 | \alias{ensure_enclosing} 5 | \alias{ensure_curly_enclosing} 6 | \alias{ensure_dash_enclosing} 7 | \title{Ensure enclosing} 8 | \usage{ 9 | ensure_curly_enclosing(raw_reassignment) 10 | 11 | ensure_dash_enclosing(raw_reassignment) 12 | } 13 | \arguments{ 14 | \item{raw_reassignment}{A character vector containing text from 15 | raw assignemnts (see 'Examples').} 16 | } 17 | \description{ 18 | Make sure a string is enclosed with some values. 19 | } 20 | \section{Functions}{ 21 | \itemize{ 22 | \item \code{ensure_curly_enclosing}: Ensures curly braces enclosing. 23 | 24 | \item \code{ensure_dash_enclosing}: Ensures dash enclosing. 25 | }} 26 | 27 | \examples{ 28 | gitsum:::ensure_curly_enclosing( 29 | c("API => api", "R/{a => b}") 30 | ) 31 | gitsum:::ensure_leading_dash( 32 | c("{API = api}", "R/{a => b}", 33 | "vignettes/{ => notes}/mysql-setup.Rmd") 34 | ) 35 | } 36 | \keyword{internal} 37 | -------------------------------------------------------------------------------- /man/ensure_gitsum_repo.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/io.R 3 | \name{ensure_gitsum_repo} 4 | \alias{ensure_gitsum_repo} 5 | \title{Make sure the repository is a gitsum repository and create one if it is not} 6 | \usage{ 7 | ensure_gitsum_repo(path = ".") 8 | } 9 | \arguments{ 10 | \item{path}{The path to the root directory of the gitsum repository.} 11 | } 12 | \description{ 13 | Make sure the repository is a gitsum repository and create one if it is not 14 | } 15 | \keyword{internal} 16 | -------------------------------------------------------------------------------- /man/expect_class.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/testing.R 3 | \name{expect_class} 4 | \alias{expect_class} 5 | \title{Class validation} 6 | \usage{ 7 | expect_class(data, class_mapping, must_check_all) 8 | } 9 | \arguments{ 10 | \item{data}{A data frame to check.} 11 | 12 | \item{class_mapping}{A data frame that contains two columns: name and class, 13 | whereas the values in name indicate the name of a column to check, class 14 | indicates the target class of the column.} 15 | 16 | \item{must_check_all}{Whether or not all columns need to be checked in order 17 | to avoid a warning.} 18 | } 19 | \description{ 20 | Check whether columns of a data frame match are of a certain class and return 21 | an informative warning otherwise. 22 | } 23 | \examples{ 24 | library(tibble) 25 | library(magrittr) 26 | class_mapping <- tribble( 27 | ~ name, ~ class, 28 | "cyl", "integer", 29 | "model", "character" 30 | ) 31 | rownames_to_column(mtcars, var= "model") \%>\% 32 | gitsum:::expect_class(class_mapping, must_check_all = FALSE) 33 | } 34 | \keyword{internal} 35 | -------------------------------------------------------------------------------- /man/extract_factory_multiple.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/extract_factories.R 3 | \name{extract_factory_multiple} 4 | \alias{extract_factory_multiple} 5 | \title{closure to extract multiple regex pattern from vector} 6 | \usage{ 7 | extract_factory_multiple(pattern) 8 | } 9 | \arguments{ 10 | \item{pattern}{The pattern the function should be able to extract.} 11 | } 12 | \description{ 13 | closure to extract multiple regex pattern from vector 14 | } 15 | \keyword{internal} 16 | -------------------------------------------------------------------------------- /man/file_path.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/renamed-files.R 3 | \name{file_path} 4 | \alias{file_path} 5 | \title{Composing file paths} 6 | \usage{ 7 | file_path(..., fsep = .Platform$file.sep) 8 | } 9 | \arguments{ 10 | \item{...}{character vectors.} 11 | 12 | \item{fsep}{the path separator to use.} 13 | } 14 | \description{ 15 | Like \code{\link[base:file.path]{base::file.path()}}, but sorts our \code{character(1)} first. 16 | } 17 | \keyword{internal} 18 | -------------------------------------------------------------------------------- /man/find_last_commit.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/io.R 3 | \name{find_last_commit} 4 | \alias{find_last_commit} 5 | \title{Find the last commit in a repo} 6 | \usage{ 7 | find_last_commit(path = ".", update_dump = FALSE) 8 | } 9 | \arguments{ 10 | \item{path}{The path to the git directory one wants to create summaries for.} 11 | 12 | \item{update_dump}{Whether or not to update the dump in .gitsum after 13 | parsing.} 14 | } 15 | \description{ 16 | Finds the last commit in a repo and optionally updates the dump. 17 | } 18 | -------------------------------------------------------------------------------- /man/find_message_and_desc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/messages.R 3 | \name{find_message_and_desc} 4 | \alias{find_message_and_desc} 5 | \title{extract message or description from a log} 6 | \usage{ 7 | find_message_and_desc(raw, target) 8 | } 9 | \arguments{ 10 | \item{raw}{A character vector corresponding to one commit.} 11 | 12 | \item{target}{either "message" or "description} 13 | } 14 | \description{ 15 | For message and description extraction, a different approach is used and 16 | one cannot rely on the approach with the simple extraction factory. 17 | } 18 | \keyword{internal} 19 | -------------------------------------------------------------------------------- /man/get_pattern_multiple.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/patterns.R 3 | \name{get_pattern_multiple} 4 | \alias{get_pattern_multiple} 5 | \title{regex patterns for extraction} 6 | \usage{ 7 | get_pattern_multiple() 8 | } 9 | \value{ 10 | returns a named vector with regex patterns to extract from a 11 | git log. 12 | } 13 | \description{ 14 | regex patterns for extraction 15 | } 16 | \keyword{internal} 17 | -------------------------------------------------------------------------------- /man/get_raw_log.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/raw_log.R 3 | \name{get_raw_log} 4 | \alias{get_raw_log} 5 | \title{Obtain the log raw data} 6 | \usage{ 7 | get_raw_log(path, file_name = NULL, remove = is.null(file_name), 8 | commit_range = NULL) 9 | } 10 | \arguments{ 11 | \item{path}{The path to the git directory one wants to create summaries for.} 12 | 13 | \item{file_name}{The name of the temporary file. If \code{NULL}, a file is 14 | created, otherwise, a file is read.} 15 | 16 | \item{remove}{Whether a log should be deleted after read in.} 17 | 18 | \item{commit_range}{A string of the form "hash1..hash2" indicating the commit 19 | range to parse. \code{NULL} means all commits.} 20 | } 21 | \description{ 22 | Obtain the log raw data 23 | } 24 | \keyword{internal} 25 | -------------------------------------------------------------------------------- /man/gitsum.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gitsum-package.R 3 | \docType{package} 4 | \name{gitsum} 5 | \alias{gitsum} 6 | \alias{gitsum-package} 7 | \title{Parse and summarize a git repository} 8 | \description{ 9 | \code{gitsum} provides tools to parse a git repository history and 10 | can create automated markdown reports from the parsed history. 11 | } 12 | \author{ 13 | Lorenz Walthert \email{lorenz.walthert@icloud.com}, \cr 14 | } 15 | -------------------------------------------------------------------------------- /man/gitsumlog.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{gitsumlog} 5 | \alias{gitsumlog} 6 | \title{Sample log data from git repository} 7 | \description{ 8 | Sample log data from git repository 9 | } 10 | \author{ 11 | Lorenz Walthert 12 | } 13 | \keyword{data} 14 | -------------------------------------------------------------------------------- /man/group_reassignment.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/renamed-files.R 3 | \name{group_reassignment} 4 | \alias{group_reassignment} 5 | \title{Create indices for splitting \code{log} into a group to update and a group to 6 | not update} 7 | \usage{ 8 | group_reassignment(log, transition) 9 | } 10 | \arguments{ 11 | \item{log}{An unnested detailed log.} 12 | 13 | \item{transition}{A named list with one entry from the transition model.} 14 | } 15 | \description{ 16 | Create indices for splitting \code{log} into a group to update and a group to 17 | not update 18 | } 19 | \keyword{internal} 20 | -------------------------------------------------------------------------------- /man/is_detailed_log.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/assert.R 3 | \name{is_detailed_log} 4 | \alias{is_detailed_log} 5 | \title{Check whether an object is a detailed log} 6 | \usage{ 7 | is_detailed_log(log, nested = NA) 8 | } 9 | \arguments{ 10 | \item{log}{The object to inspect.} 11 | 12 | \item{nested}{Whether or not the object to inspect should be nested or not. 13 | \code{NA} indicates that both nested and unnested logs shoud pass the 14 | inspection.} 15 | } 16 | \description{ 17 | Check whether an object is a detailed log 18 | } 19 | \keyword{internal} 20 | -------------------------------------------------------------------------------- /man/is_name_change.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/renamed-files.R 3 | \name{is_name_change} 4 | \alias{is_name_change} 5 | \title{Detect whether a \code{changed_file}-entry is a renaming} 6 | \usage{ 7 | is_name_change(changed_file, 8 | reassignment_pattern = ".+\\\\s\\\\=\\\\>.+$") 9 | } 10 | \arguments{ 11 | \item{changed_file}{The column \code{changed_file} from a parsed unnested 12 | detailed log as a vector.} 13 | 14 | \item{reassignment_pattern}{The regular expression pattern that corresponds 15 | to renaming.} 16 | } 17 | \description{ 18 | Filenames in \code{$ git log} containing the sequence \code{=>} are viewed as renamed 19 | files. There seems no other way around that, so this function will indicate 20 | a file is a name change even if it may not be the case. 21 | } 22 | \examples{ 23 | gitsum:::is_name_change(c( 24 | "R/{gitsum.R => gitsum-package.R}", "API => API2", 25 | "this is jus a file with => in it, it's not a name change" 26 | )) 27 | } 28 | \keyword{internal} 29 | -------------------------------------------------------------------------------- /man/manage_gitsum.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/io.R 3 | \name{manage_gitsum} 4 | \alias{manage_gitsum} 5 | \alias{init_gitsum} 6 | \alias{remove_gitsum} 7 | \title{Manage a gitsum repository} 8 | \usage{ 9 | init_gitsum(path = ".", over_write = FALSE) 10 | 11 | remove_gitsum(path = ".") 12 | } 13 | \arguments{ 14 | \item{path}{The path to the repository to initialize.} 15 | 16 | \item{over_write}{Whether or not an existing directory should be overwritten.} 17 | } 18 | \description{ 19 | A gitsum repository is a git repository with an additional .gitsum folder in 20 | the root directory that is mainly used to store a parsed git log as a tibble. 21 | } 22 | \section{Functions}{ 23 | \itemize{ 24 | \item \code{init_gitsum}: Calling this function will parse the available git 25 | history and dump it into the directory .gitsum. 26 | 27 | \item \code{remove_gitsum}: Removes the gitsum repository, i.e just the folder 28 | .gitsum and its contents. 29 | }} 30 | 31 | -------------------------------------------------------------------------------- /man/nest_log.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/nest.R 3 | \name{nest_log} 4 | \alias{nest_log} 5 | \alias{unnest_log} 6 | \title{Nest/unnest a gitsum log} 7 | \usage{ 8 | nest_log(log) 9 | 10 | unnest_log(log) 11 | } 12 | \arguments{ 13 | \item{log}{A log to nest/unnest.} 14 | } 15 | \description{ 16 | Forwards to \code{\link[tidyr:nest]{tidyr::nest()}} while taking care of which columns have to be 17 | nested. 18 | 19 | Forwards to \code{\link[tidyr:unnest]{tidyr::unnest()}} while taking care of which columns have to be 20 | nested unnested. 21 | } 22 | -------------------------------------------------------------------------------- /man/parse_lines.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/parse.R 3 | \name{parse_lines} 4 | \alias{parse_lines} 5 | \title{Turn a raw log of lines into a tabular format} 6 | \usage{ 7 | parse_lines(lines) 8 | } 9 | \arguments{ 10 | \item{lines}{The output of \code{\link[=get_raw_log]{get_raw_log()}}.} 11 | } 12 | \description{ 13 | Turn a raw log of lines into a tabular format 14 | } 15 | \keyword{internal} 16 | -------------------------------------------------------------------------------- /man/parse_log_detailed.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/detailed.R 3 | \name{parse_log_detailed} 4 | \alias{parse_log_detailed} 5 | \alias{parse_log_detailed_full_run} 6 | \title{Obtain a detailed git log} 7 | \usage{ 8 | parse_log_detailed(path = ".", update_dump = TRUE) 9 | 10 | parse_log_detailed_full_run(path = ".", na_to_zero = TRUE, 11 | file_name = NULL, commit_range = NULL) 12 | } 13 | \arguments{ 14 | \item{path}{The path to the git directory one wants to create summaries for.} 15 | 16 | \item{update_dump}{Whether or not to update the dump in .gitsum after 17 | parsing.} 18 | 19 | \item{na_to_zero}{Whether some \code{NA} values should be converted to zero. 20 | See 'Details'.} 21 | 22 | \item{file_name}{The path to a raw log. If \code{NULL}, a raw log is created and 23 | read in and deleted after read-in, otherwise, an existing log is read.} 24 | 25 | \item{commit_range}{A string of the form "hash1..hash2" indicating the commit 26 | range to parse. \code{NULL} means all commits.} 27 | } 28 | \value{ 29 | A parsed git log as a nested tibble. Each line corresponds to a 30 | commit. The unnested column names are: \cr 31 | short_hash, author_name, date, short_message, hash, left_parent, 32 | right_parent, author_email, weekday, month, monthday, time, year, timezone, 33 | message, description, total_files_changed, total_insertions, 34 | total_deletions, short_description, is_merge \cr 35 | The nested columns contain more information on each commit. The column 36 | names are: \cr 37 | changed_file, edits, insertions, deletions. 38 | } 39 | \description{ 40 | This function returns a git log in a tabular format. 41 | } 42 | \details{ 43 | \itemize{ 44 | \item Note that for merge commits, the following columns are \code{NA} if 45 | the option \code{na_to_zero} is set to \code{FALSE}.: 46 | total_files_changed, total_insertions, total_deletions, changed_file, 47 | edits, deletions, insertions. 48 | \item Note that for binary files, the following columns are 0: edits, deletions, 49 | insertions. 50 | } 51 | } 52 | \section{Functions}{ 53 | \itemize{ 54 | \item \code{parse_log_detailed_full_run}: In contrast to parse_log_detailed, this function 55 | does not read any history from the .gitum directory. 56 | }} 57 | 58 | \section{Warning}{ 59 | 60 | The number of edits, insertions, and deletions (on a file level) are based 61 | on \code{git log --stat} and the number of \code{+} and \code{-} in this log. The number 62 | of \code{+} and \code{-} may not sum up to the edits indicated as a scalar after "|" 63 | in \code{git log --stat} 64 | for commits with very many changed lines since for those, the \code{+} and \code{-} 65 | only indicate the relative share of insertions and edits. Therefore, 66 | \code{parse_log_detailed_full_run()} normalizes the insertions and deletions and rounds 67 | these after the normalization to achieve more consistent results. However, 68 | there is no guarantee that these numbers are always exact. The column 69 | is_exact indicates for each changed file within a commit whether the result 70 | is exact (which is the case if the normalizing constant was one). 71 | } 72 | 73 | \seealso{ 74 | See \link{parse_log_simple} for a fast alternative with less information. 75 | } 76 | -------------------------------------------------------------------------------- /man/parse_log_one.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/parse.R 3 | \name{parse_log_one} 4 | \alias{parse_log_one} 5 | \title{parse a raw log} 6 | \usage{ 7 | parse_log_one(raw, fnc_list, has_merge) 8 | } 9 | \arguments{ 10 | \item{raw}{a character vector corresponding to one commit.} 11 | 12 | \item{fnc_list}{the list of named functions that return the elements 13 | we want to extract from the log, i.e. author, hash etc.} 14 | 15 | \item{has_merge}{Whether or not \code{raw} is a merge commit. This is relevant 16 | because merge commits have additional lines.} 17 | } 18 | \description{ 19 | parse a raw log 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/parse_log_simple.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/simple.R 3 | \name{parse_log_simple} 4 | \alias{parse_log_simple} 5 | \title{Obtain a simple log for a git repo} 6 | \usage{ 7 | parse_log_simple(path = ".", file_name = NULL) 8 | } 9 | \arguments{ 10 | \item{path}{The path to the git directory one wants to create summaries for.} 11 | 12 | \item{file_name}{The path to a raw log. If \code{NULL}, a raw log is created and 13 | read in and deleted after read-in, otherwise, an existing log is read.} 14 | } 15 | \description{ 16 | This function returns a git log in a tabular format. 17 | } 18 | \seealso{ 19 | See \link{parse_log_detailed} for a slower alternative with more 20 | information. 21 | } 22 | -------------------------------------------------------------------------------- /man/parse_reassignment.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/renamed-files.R 3 | \name{parse_reassignment} 4 | \alias{parse_reassignment} 5 | \title{Parse a raw reassignment into a list} 6 | \usage{ 7 | parse_reassignment(raw_reassignment, reassignment_index) 8 | } 9 | \arguments{ 10 | \item{raw_reassignment}{Character vector with raw re-assignments.} 11 | 12 | \item{reassignment_index}{Integer vector indicating the position of the 13 | re-assignment in the original unnested detailed log.} 14 | } 15 | \description{ 16 | Takes a vector of raw reassignments and turns them into a list of elements. 17 | Every element contains the old path, the new path and the index of the 18 | reassignment. 19 | } 20 | \examples{ 21 | gitsum:::parse_reassignment( 22 | c("R/{a => b}", "API => api2", "{src => inst/include}/dplyr_types.h"), 23 | c(1, 2, 33) 24 | ) 25 | } 26 | \keyword{internal} 27 | -------------------------------------------------------------------------------- /man/parse_test_log.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/testing.R 3 | \name{parse_test_log} 4 | \alias{parse_test_log} 5 | \title{Parse a test log} 6 | \usage{ 7 | parse_test_log(path_to_raw_log, parser = parse_log_detailed_full_run, 8 | ...) 9 | } 10 | \arguments{ 11 | \item{path_to_raw_log}{The path to the raw log relative to tests/testthat/.} 12 | 13 | \item{parser}{The parser to use, i.e. either \code{\link[=parse_log_detailed_full_run]{parse_log_detailed_full_run()}} 14 | or \code{\link[=parse_log_simple]{parse_log_simple()}}.} 15 | 16 | \item{...}{Params passed to \code{\link[=parse_log_detailed_full_run]{parse_log_detailed_full_run()}}.} 17 | } 18 | \description{ 19 | Function to facilitate the reading and parsing of a raw log for unit test 20 | purposes. 21 | } 22 | \keyword{internal} 23 | -------------------------------------------------------------------------------- /man/read_gitsum.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/io.R 3 | \name{read_gitsum} 4 | \alias{read_gitsum} 5 | \alias{read_log} 6 | \alias{read_last_commit} 7 | \alias{read_last_hash} 8 | \title{Read gitsum data into R} 9 | \usage{ 10 | read_log(path = ".") 11 | 12 | read_last_commit(path = ".") 13 | 14 | read_last_hash(path = ".") 15 | } 16 | \arguments{ 17 | \item{path}{The path to the root directory of the gitsum repository.} 18 | } 19 | \description{ 20 | Read gitsum data into R 21 | } 22 | \section{Functions}{ 23 | \itemize{ 24 | \item \code{read_log}: Reads a parsed log. 25 | 26 | \item \code{read_last_commit}: Reads the last parsed commit. 27 | 28 | \item \code{read_last_hash}: Reads the last parsed hash. 29 | }} 30 | 31 | \keyword{internal} 32 | -------------------------------------------------------------------------------- /man/report_git.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/reports.R 3 | \name{report_git} 4 | \alias{report_git} 5 | \title{Create a summary report of a git repository} 6 | \usage{ 7 | report_git(path = ".", output_file = NULL, 8 | output_format = "html_document", 9 | template = "gitsum::repo_summary_simple", input_file = NULL, 10 | directory = "gitsum", cached = TRUE, .libpath_index = 1) 11 | } 12 | \arguments{ 13 | \item{path}{The path to the git directory one wants to create summaries for.} 14 | 15 | \item{output_file}{The name of the output file. If using \code{NULL} then the 16 | output filename will be based on filename for the input file. If a filename 17 | is provided, a path to the output file can also be provided. Note that the 18 | \code{output_dir} option allows for specifying the output file path as well, 19 | however, if also specifying the path, the directory must exist. If 20 | \code{output_file} is specified but does not have a file extension, an 21 | extension will be automatically added according to the output format. To 22 | avoid the automatic file extension, put the \code{output_file} value in 23 | \code{\link{I}()}, e.g., \code{I('my-output')}.} 24 | 25 | \item{output_format}{The R Markdown output format to convert to. The option 26 | \code{"all"} will render all formats defined within the file. The option can 27 | be the name of a format (e.g. \code{"html_document"}) and that will render 28 | the document to that single format. One can also use a vector of format 29 | names to render to multiple formats. Alternatively, you can pass an output 30 | format object (e.g. \code{html_document()}). If using \code{NULL} then the 31 | output format is the first one defined in the YAML frontmatter in the input 32 | file (this defaults to HTML if no format is specified there).} 33 | 34 | \item{template}{the template file to be used. Either one from a package 35 | (e.g. \code{gitsum::repo_summary_simple}), or a user defined template, 36 | which is then indicated with a path to this file including extension, i.e. 37 | \code{/users/xzy/a_template.Rmd}.} 38 | 39 | \item{input_file}{the name of the temporary file that contains log data on 40 | which the report is base on. If \code{NULL}, a log file is created according to 41 | \code{path}, otherwise, a file is read.} 42 | 43 | \item{directory}{A directory to which the reports should be stored.} 44 | 45 | \item{cached}{Whether or not the report should be cached with rmarkdown, so 46 | the graphs are written to a file.} 47 | 48 | \item{.libpath_index}{index of the Library according to \link[base:libPaths]{base::libPaths} in 49 | which the template should be searched. The list with the available 50 | directories is returned invisibly for situations in which \code{.libPaths()} 51 | cannot be emulated.} 52 | } 53 | \description{ 54 | Producing a summary report of a repo. 55 | } 56 | \details{ 57 | Other packages can define templates. They must be store an .Rmd 58 | template in inst/report_templates. The data passed to the report template 59 | is log, the parsed log table. 60 | } 61 | -------------------------------------------------------------------------------- /man/separate_dir_and_reassignment.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/renamed-files.R 3 | \name{separate_dir_and_reassignment} 4 | \alias{separate_dir_and_reassignment} 5 | \title{Separate the directory from the reassignment} 6 | \usage{ 7 | separate_dir_and_reassignment(raw_reassignment) 8 | } 9 | \arguments{ 10 | \item{raw_reassignment}{Character vector with raw re-assignments.} 11 | } 12 | \description{ 13 | Splits according to regex "/\{|\}/". 14 | } 15 | \examples{ 16 | gitsum:::separate_dir_and_reassignment("R/{gitsum.R => gitsum-package.R}/") 17 | } 18 | \keyword{internal} 19 | -------------------------------------------------------------------------------- /man/set_changed_file_to_latest_name.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/renamed-files.R 3 | \name{set_changed_file_to_latest_name} 4 | \alias{set_changed_file_to_latest_name} 5 | \title{Use the latest name of a file in every log entry} 6 | \usage{ 7 | set_changed_file_to_latest_name(log) 8 | } 9 | \arguments{ 10 | \item{log}{An unnested detailed log.} 11 | } 12 | \description{ 13 | Set the column \code{changed_files} of a \code{log} to the latest name of the file 14 | } 15 | \details{ 16 | \code{\link[=parse_log_detailed]{parse_log_detailed()}} parses a git log. However, changed file names 17 | are not corrected retroactively. Hence, if one wants to process file-specific 18 | commit data for one file across different names for that file, the column 19 | \code{changed_files} has to be unified. This is done with this function by 20 | updating the file names recursively and setting them to the latest name used. 21 | Filenames containing the sequence \code{=>} are viewed as renamed files, so 22 | there will likely be problems when you apply this function to a git 23 | repository that contains (or contained) files with such files names. You 24 | may have to update the column \code{changed_file} manually. 25 | } 26 | \examples{ 27 | library("magrittr") 28 | gitsumlog \%>\% 29 | tidyr::unnest() \%>\% 30 | set_changed_file_to_latest_name() \%>\% 31 | add_line_history() 32 | } 33 | -------------------------------------------------------------------------------- /man/testthat_file.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/testing.R 3 | \name{testthat_file} 4 | \alias{testthat_file} 5 | \title{Create the path to a test that file} 6 | \usage{ 7 | testthat_file(...) 8 | } 9 | \arguments{ 10 | \item{...}{Arguments passed to \code{\link[=file.path]{file.path()}} to construct the path after 11 | ".../tests/testthat/"} 12 | } 13 | \description{ 14 | Create the path to a test that file 15 | } 16 | \keyword{internal} 17 | -------------------------------------------------------------------------------- /man/update_changed_file.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/renamed-files.R 3 | \name{update_changed_file} 4 | \alias{update_changed_file} 5 | \title{Apply one file name update to a log} 6 | \usage{ 7 | update_changed_file(log, transition) 8 | } 9 | \arguments{ 10 | \item{log}{An unnested detailed log.} 11 | 12 | \item{transition}{A named list with one entry from the transition model.} 13 | } 14 | \description{ 15 | Apply one file name update to a log 16 | } 17 | \keyword{internal} 18 | -------------------------------------------------------------------------------- /man/update_changed_file_one.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/renamed-files.R 3 | \name{update_changed_file_one} 4 | \alias{update_changed_file_one} 5 | \title{Apply one file name update to an unnested log that contains commits 6 | up to that name change. Also needs to update the last entry in log, which 7 | is the transition itself.} 8 | \usage{ 9 | update_changed_file_one(log, transition) 10 | } 11 | \arguments{ 12 | \item{log}{An unnested detailed log.} 13 | 14 | \item{transition}{A named list with one entry from the transition model.} 15 | } 16 | \description{ 17 | Apply one file name update to an unnested log that contains commits 18 | up to that name change. Also needs to update the last entry in log, which 19 | is the transition itself. 20 | } 21 | \keyword{internal} 22 | -------------------------------------------------------------------------------- /man/update_changed_file_sequentially.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/renamed-files.R 3 | \name{update_changed_file_sequentially} 4 | \alias{update_changed_file_sequentially} 5 | \title{Apply all updates of file names sequentially to a log} 6 | \usage{ 7 | update_changed_file_sequentially(log, transition_model) 8 | } 9 | \arguments{ 10 | \item{log}{An unnested detailed log.} 11 | 12 | \item{transition_model}{A transition model obtained from 13 | \code{\link[=parse_reassignment]{parse_reassignment()}}.} 14 | } 15 | \description{ 16 | Recursively updates the column \code{changed_file} of \code{log} according to a 17 | transition scheme provided in \code{transition_model}. 18 | } 19 | \keyword{internal} 20 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(gitsum) 3 | 4 | test_check("gitsum") 5 | -------------------------------------------------------------------------------- /tests/testthat/reference-objects/combine-dir-and-base: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/reference-objects/combine-dir-and-base -------------------------------------------------------------------------------- /tests/testthat/reference-objects/nest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/reference-objects/nest -------------------------------------------------------------------------------- /tests/testthat/reference-objects/parse-reassignment: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/reference-objects/parse-reassignment -------------------------------------------------------------------------------- /tests/testthat/reference-objects/parse-reassignment-complex: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/reference-objects/parse-reassignment-complex -------------------------------------------------------------------------------- /tests/testthat/reference-objects/parse-reassignment-complex2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/reference-objects/parse-reassignment-complex2 -------------------------------------------------------------------------------- /tests/testthat/reference-objects/separate-dir-and-assignment: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/reference-objects/separate-dir-and-assignment -------------------------------------------------------------------------------- /tests/testthat/reference-objects/unnest: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/reference-objects/unnest -------------------------------------------------------------------------------- /tests/testthat/test-assert-log.R: -------------------------------------------------------------------------------- 1 | context("test-assert-log.R") 2 | 3 | parsed_log <- parse_test_log_detailed("test_logs/testthat_log_detailed.txt") 4 | 5 | test_that("Can assert log", { 6 | expect_silent(assert_detailed_log(parsed_log)) 7 | expect_silent(assert_detailed_log(parsed_log, nested = TRUE)) 8 | expect_error(assert_detailed_log(parsed_log, nested = FALSE)) 9 | 10 | expect_error(assert_detailed_log(mtcars)) 11 | expect_error(assert_detailed_log(unnest_log(parsed_log), nested = TRUE)) 12 | expect_silent(assert_detailed_log(unnest_log(parsed_log), nested = FALSE)) 13 | }) 14 | -------------------------------------------------------------------------------- /tests/testthat/test-backend.R: -------------------------------------------------------------------------------- 1 | context("test backend") 2 | test_that("repo can be created", { 3 | skip_on_os("windows") 4 | remove_gitsum() 5 | expect_error(init_gitsum("."), NA) 6 | expect_true(dir.exists(".gitsum")) 7 | }) 8 | 9 | test_that("dump can be read", { 10 | skip_on_os("windows") 11 | expect_error(read_log(), NA) 12 | expect_error(read_last_commit(), NA) 13 | expect_error(read_last_hash(), NA) 14 | }) 15 | 16 | test_that("repo can be removed", { 17 | skip_on_os("windows") 18 | expect_error(remove_gitsum(), NA) 19 | }) 20 | -------------------------------------------------------------------------------- /tests/testthat/test-dir-reports/.gitsum/last_commit.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/test-dir-reports/.gitsum/last_commit.rds -------------------------------------------------------------------------------- /tests/testthat/test-dir-reports/.gitsum/log.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/test-dir-reports/.gitsum/log.rds -------------------------------------------------------------------------------- /tests/testthat/test-dir/.gitsum/last_commit.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/test-dir/.gitsum/last_commit.rds -------------------------------------------------------------------------------- /tests/testthat/test-dir/.gitsum/log.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/test-dir/.gitsum/log.rds -------------------------------------------------------------------------------- /tests/testthat/test-log_outputs.R: -------------------------------------------------------------------------------- 1 | context("sample logs and names") 2 | 3 | log_simp <- testthat_file("test_logs/log_out_simp.rds") 4 | log_det <- testthat_file("test_logs/log_out_det.rds") 5 | 6 | git_det <- parse_test_log_detailed("test_logs/testthat_log_detailed.txt") 7 | git_simp <- parse_test_log_simple("test_logs/testthat_log_simple.txt") 8 | 9 | test_that("simple log output is correct", { 10 | expect_is(git_simp, "tbl_df") 11 | expect_named(git_simp, c( 12 | "author", "message_short", "date", "commit", 13 | "weekday", "month", "monthday", "time", "year", 14 | "message", "left_parent", "right_parent", "n_parents" 15 | )) 16 | 17 | expect_equal_to_reference(git_simp, log_simp) 18 | }) 19 | 20 | test_that("advanced log output is correct", { 21 | expect_is(git_det, "tbl_df") 22 | expect_named(git_det, c( 23 | "short_hash", "author_name", "date", "short_message", "hash", 24 | "left_parent", "right_parent", "author_email", "weekday", "month", 25 | "monthday", "time", "year", "timezone", "message", "description", 26 | "total_files_changed", "total_insertions", "total_deletions", 27 | "commit_nr", "short_description", "is_merge", "nested" 28 | )) 29 | expect_equal_to_reference(unnest(git_det, .data$nested), log_det) 30 | }) 31 | -------------------------------------------------------------------------------- /tests/testthat/test-nest.R: -------------------------------------------------------------------------------- 1 | context("nesting") 2 | 3 | parsed_log <- parse_test_log_detailed("test_logs/testthat_log_detailed.txt") 4 | 5 | test_that("can unnest", { 6 | expect_known_output(unnest_log(parsed_log), testthat_file("reference-objects/unnest")) 7 | expect_warning(unnest_log(unnest_log(parsed_log))) 8 | }) 9 | 10 | test_that("can nest", { 11 | expect_known_output( 12 | nest_log(unnest_log(parsed_log)), testthat_file("reference-objects/nest") 13 | ) 14 | expect_warning(nest_log(nest_log(unnest_log(parsed_log)))) 15 | }) 16 | -------------------------------------------------------------------------------- /tests/testthat/test-renaming.R: -------------------------------------------------------------------------------- 1 | context("renaming - helper") 2 | 3 | raw <- c( 4 | trailing_extension = "{src => inst/include}/dplyr_types.h", 5 | bothsided_extension = "vignettes/{ => notes}/mysql-setup.Rmd", 6 | leading_extension = "man/{get_log_regex.Rd => git_log_detailed.Rd}", 7 | no_extension = "API => api" 8 | ) %>% 9 | unname() 10 | 11 | raw_after_curly <- c( 12 | "{src => inst/include}/dplyr_types.h", 13 | "vignettes/{ => notes}/mysql-setup.Rmd", 14 | "man/{get_log_regex.Rd => git_log_detailed.Rd}", 15 | "{API => api}" 16 | ) 17 | 18 | test_that("curly enclosing", { 19 | expect_equal(ensure_curly_enclosing(raw), raw_after_curly) 20 | }) 21 | 22 | test_that("dash enclosing", { 23 | expect_equal(ensure_dash_enclosing(raw_after_curly), c( 24 | "/{src => inst/include}/dplyr_types.h", 25 | "vignettes/{ => notes}/mysql-setup.Rmd", 26 | "man/{get_log_regex.Rd => git_log_detailed.Rd}/", 27 | "/{API => api}/" 28 | )) 29 | }) 30 | 31 | test_that("parse the full reassignment", { 32 | parsed_reassignment <- parse_reassignment( 33 | c("R/{a => b}", "API => api2", "{src => inst/include}/dplyr_types.h"), 34 | c(1, 2, 33) 35 | ) 36 | 37 | expect_known_output( 38 | parsed_reassignment, 39 | testthat_file("reference-objects/parse-reassignment-complex") 40 | ) 41 | }) 42 | 43 | test_that("parse the full reassignment", { 44 | expect_known_output( 45 | parse_reassignment("vignettes/{ => internals}/hybrid-evaluation.Rmd", 23), 46 | testthat_file("reference-objects/parse-reassignment-complex2") 47 | ) 48 | }) 49 | 50 | context("renaming") 51 | 52 | test_that("name change", { 53 | expect_true(is_name_change("man/{get_log_regex.Rd => git_log_detailed.Rd}")) 54 | expect_true(!is_name_change("inst/report_templates/repo_summary_simple.Rmd")) 55 | }) 56 | 57 | 58 | test_that("parsing", { 59 | expect_known_output( 60 | parse_reassignment(rep("R/{a => b}", 2), c(1, 2)), 61 | testthat_file("reference-objects/parse-reassignment") 62 | ) 63 | }) 64 | 65 | test_that("dir and base assignment", { 66 | expect_known_output( 67 | separate_dir_and_reassignment("R/{gitsum.R => gitsum-package.R}"), 68 | testthat_file("reference-objects/separate-dir-and-assignment") 69 | ) 70 | expect_known_output( 71 | combine_dir_and_base("R", list(c("a", "b")), "", 1), 72 | testthat_file("reference-objects/combine-dir-and-base") 73 | ) 74 | }) 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /tests/testthat/test-report_generation.R: -------------------------------------------------------------------------------- 1 | context("plots") 2 | library("ggplot2") 3 | path_det <- testthat_file("test_logs/testthat_log_detailed.txt") 4 | test_that("repo reports can be created", { 5 | skip_on_os("windows") 6 | if (!is_gitsum_repo()) init_gitsum() 7 | expect_error(report_git( 8 | path = dirname(path_det), 9 | cached = FALSE, 10 | input_file = basename(path_det), 11 | output_format = "all" 12 | ), NA) 13 | }) 14 | -------------------------------------------------------------------------------- /tests/testthat/test-testing.R: -------------------------------------------------------------------------------- 1 | context("test-testing.R") 2 | 3 | test_that("expect_class() works", { 4 | class_mapping <- tibble::tribble( 5 | ~ name, ~ class, 6 | "cyl", "integer", 7 | "model", "character" 8 | ) 9 | tbl <- tibble::rownames_to_column(mtcars, var= "model") 10 | 11 | expect_warning( 12 | expect_class(tbl, class_mapping, must_check_all = FALSE), 13 | "class for cyl was numeric, but integer was expected" 14 | ) 15 | }) 16 | -------------------------------------------------------------------------------- /tests/testthat/test-type-stability.R: -------------------------------------------------------------------------------- 1 | context("test-type-stability.R") 2 | 3 | detailed_log <- parse_test_log_detailed("test_logs/testthat_log_detailed.txt") 4 | 5 | test_that("detailed log returns correct classes", { 6 | mapping <- tibble::tribble( 7 | ~name, ~class, 8 | "short_hash", "character", 9 | "author_name", "character", 10 | "date", "POSIXct", 11 | "short_message", "character", 12 | "commit_nr", "integer", 13 | "left_parent", "character", 14 | "right_parent", "character", 15 | "author_email", "character", 16 | "weekday", "character", 17 | "month", "character", 18 | "hash", "character", 19 | "monthday", "integer", 20 | "time", "hms", 21 | "year", "integer", 22 | "timezone", "character", 23 | "message", "character", 24 | "description", "character", 25 | "total_files_changed", "integer", 26 | "total_insertions", "integer", 27 | "total_deletions", "integer", 28 | "short_description", "character", 29 | "is_merge", "logical", 30 | "changed_file", "character", 31 | "edits", "integer", 32 | "insertions", "integer", 33 | "deletions", "integer", 34 | "is_exact", "logical" 35 | ) 36 | expect_silent(expect_class( 37 | unnest_log(detailed_log), mapping, must_check_all = TRUE 38 | )) 39 | }) 40 | -------------------------------------------------------------------------------- /tests/testthat/test_logs/log_out_det.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/test_logs/log_out_det.rds -------------------------------------------------------------------------------- /tests/testthat/test_logs/log_out_simp.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lorenzwalthert/gitsum/33555bc87854212f4f37a37ab9c22c043e9b85eb/tests/testthat/test_logs/log_out_simp.rds -------------------------------------------------------------------------------- /tests/testthat/test_logs/testthat_log_simple.txt: -------------------------------------------------------------------------------- 1 | 5970123 Lorenz Walthert Fri May 26 23:06:16 2017 fixing broken built and bugs add203ad3b5186265c59d3bbeab57a5a1d612a1c 2 | add203a Lorenz Walthert Fri May 26 23:03:27 2017 Merge pull request #6 from jonmcalder/master 652913565c827985e37d5b8b7bc39fe7a58436fd aa546cf0e64775a109c86230c6099c5f6a1ed5a1 3 | aa546cf Jon Calder Fri May 26 18:01:16 2017 Fix failing tests 652913565c827985e37d5b8b7bc39fe7a58436fd 4 | 6529135 Lorenz Walthert Fri May 26 17:22:16 2017 some tests eb79a4d52a855235e6245238075e16d616bb6d7b 5 | eb79a4d Lorenz Walthert Fri May 26 16:49:21 2017 merge @jonmcalder's PR manually da5c68a831140598c7d906c550c495c3e9d3ecd0 f0109908463a7f73fdb970434fc68f0827ca1519 6 | da5c68a Lorenz Walthert Fri May 26 16:11:34 2017 ungroup to aviod error under tidyr 0.6.3.9000 424d749a1a1461d376c7beab74d09d0f02fb4a8b 7 | 424d749 Lorenz Walthert Thu May 25 23:25:31 2017 doc and report f276274c8b30ece39f1f5dbd040fd2479c3b3a1f 8 | f276274 Lorenz Walthert Thu May 25 23:25:31 2017 some more documentation f33980165e1a216856634bc8cd76ebc27b0b2a1f 9 | f339801 Lorenz Walthert Thu May 25 18:28:18 2017 fix bug for binary files 12bdfa391a77aeea4c3cf26dcea41ce5b32a571d 10 | 12bdfa3 Lorenz Walthert Thu May 25 18:27:51 2017 add section on report generation 367f4a993425bd265ac7f9a3b6d554b3a1086486 11 | 367f4a9 Lorenz Walthert Thu May 25 17:31:31 2017 bug fix with multiline messages 1c993ec09f501329e9dd987d4a7c011bf0f2b38b 12 | 1c993ec Lorenz Walthert Thu May 25 16:35:24 2017 Merge pull request #5 from lorenzwalthert/speedup 2a5ad456b4e5866949fa1788658cae73920a386d 5506d070770dd6dff2673cb801412f3dd2e48a36 13 | 5506d07 Lorenz Walthert Thu May 25 16:28:27 2017 add benchmarking and data da87db7057a02a929d3bffb45e99c10b2919cfe4 14 | da87db7 Lorenz Walthert Thu May 25 15:06:41 2017 major update a5a23dc8bb6b59d5249da853745cda67c1c146d2 15 | a5a23dc Lorenz Walthert Thu May 25 09:11:12 2017 use dplyr::do approach rather than two nested lapply 64135ef75d4f76ae74a4a9c1c807b5f28eefce34 16 | 64135ef Lorenz Walthert Wed May 24 22:21:09 2017 correct function description 39936d200d96a0ddf51878eb5d13ec2dabec0f3b 17 | f010990 jonmcalder Sat May 20 23:49:40 2017 Merge branch 'master' of https://github.com/jonmcalder/gitsum 03281483f725dce1b3369c508b2c04cf0dc2f1af 22a6bd3bf43875290e42eef748e230faa6210380 18 | 0328148 jonmcalder Sat May 20 23:48:35 2017 Add tests and fix get_simple_log() 458eda1338f0ffc981cbe3dd84bb1f745041e4f8 19 | 39936d2 Lorenz Walthert Sat May 20 22:50:31 2017 don't rebuilt test_repos 4591cb285cf8dfa684065415fa4fc04781201445 20 | 4591cb2 Lorenz Walthert Sat May 20 22:33:30 2017 add untracked test_repos 311d1286579f4c59429af0d09a38c54a060c61c2 21 | 311d128 Lorenz Walthert Sat May 20 22:18:26 2017 add get_raw_log and option to specify file to read log from. 03aea248dd1f57619cc27e5e3cc1e03b2e39e469 22 | 03aea24 Lorenz Walthert Sat May 20 20:41:07 2017 update doc b2c5a55276bcba287625f920d7831892d82df415 23 | b2c5a55 Lorenz Walthert Sat May 20 20:40:56 2017 add gitsum a5d23dcc163cca66e62b499c601315fc2b6fd558 24 | a5d23dc Lorenz Walthert Sat May 20 20:38:05 2017 add report function 2a5ad456b4e5866949fa1788658cae73920a386d 25 | 2a5ad45 Lorenz Walthert Sat May 20 17:11:59 2017 Merge pull request #1 from jonmcalder/master a0b11e22a64165b72886717e097e19744a9ed9ea 22a6bd3bf43875290e42eef748e230faa6210380 26 | 22a6bd3 Jon Calder Sat May 20 17:07:28 2017 Merge branch 'master' into master 458eda1338f0ffc981cbe3dd84bb1f745041e4f8 a0b11e22a64165b72886717e097e19744a9ed9ea 27 | 458eda1 jonmcalder Sat May 20 17:05:20 2017 Make get_log platform dependent & update README fa5530ac2d5f89ea73af52a136f92d99389982c9 28 | a0b11e2 Lorenz Walthert Sat May 20 15:18:13 2017 add travis / codecov badges 90df1d1c62409064c252fd080718fdd824c26d32 29 | fa5530a jonmcalder Sat May 20 02:05:11 2017 Get rid of unnecessary package warnings in README 29baa31982c529dc9cab9ba9448d6e3d7d3426ed 30 | 29baa31 jonmcalder Sat May 20 01:51:03 2017 Update README 5d3285ed873e9ca9095fe34d12576aed6633e13a 31 | 5d3285e jonmcalder Sat May 20 01:39:43 2017 Update create_log() to make it work on Windows, fix LICENSE & update README 90df1d1c62409064c252fd080718fdd824c26d32 32 | 90df1d1 Lorenz Walthert Fri May 19 21:51:31 2017 fix regex 7be697a801711112b79cef2720c5fd46e3311e60 33 | 7be697a Lorenz Walthert Fri May 19 21:42:58 2017 add md anyways 4fc09ed9b786de961fbf3e55743d80a7355bf697 34 | 4fc09ed Lorenz Walthert Fri May 19 21:40:24 2017 remove garbage 917ed5cd77a5b0195e044287455a7e69e94fbab5 35 | 917ed5c Lorenz Walthert Fri May 19 21:32:40 2017 update infrastructure 943ccc93435bd1bf8a4468f797d8326023d13c60 36 | 943ccc9 Lorenz Walthert Fri May 19 21:32:24 2017 add helpfiles 7a2a008e60dc383252ab65ba3698bb63b90780a4 37 | 7a2a008 Lorenz Walthert Fri May 19 21:31:54 2017 document log data 2ac3b0a38a723d052f21606b2e81e2b18f22ba70 38 | 2ac3b0a Lorenz Walthert Fri May 19 21:31:43 2017 add readme 7825e7296a7a0e6e2d338422b63623b8bb548ac2 39 | 7825e72 Lorenz Walthert Fri May 19 21:31:03 2017 add licence dfab201e440af4c357caac19730597a49b492d92 40 | dfab201 Lorenz Walthert Fri May 19 17:00:40 2017 intermediate 63281c3cd551897f73d085dabf51eddbe7abb628 41 | 63281c3 Lorenz Walthert Fri May 19 14:26:53 2017 add parents f8ee8fb7858f80f14ed90e8435507ce93f5a8fd7 42 | f8ee8fb Lorenz Walthert Fri May 19 14:26:32 2017 add log example data 243fcdb3275a6563b25d1909a6ab94066412a8d7 43 | 243fcdb Lorenz Walthert Fri May 19 11:23:23 2017 initial commit -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /vignettes/renaming.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Renaming" 3 | author: "Lorenz Walthert" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Renaming} 8 | %\VignetteEngine{knitr::rmarkdown} 9 | %\VignetteEncoding{UTF-8} 10 | --- 11 | 12 | ```{r setup, include = FALSE} 13 | knitr::opts_chunk$set( 14 | collapse = TRUE, 15 | comment = "#>", 16 | eval = FALSE 17 | ) 18 | ``` 19 | 20 | # Input cases 21 | 22 | ## base case 23 | Renaming a file in a directory. 24 | ```{r} 25 | "R/{rbind.r => bind.r}" 26 | ``` 27 | 28 | A file name change may not have `{` 29 | ```{r} 30 | "API => API2" 31 | ``` 32 | 33 | 34 | 35 | ## add directory in between 36 | rename from vignettes/vagrant-setup.Rmd to vignettes/notes/vagrant-setup.Rmd 37 | ```{r} 38 | "vignettes/{ => notes}/mysql-setup.Rmd" 39 | ``` 40 | 41 | 42 | 43 | ## rename directory 44 | rename from src/dplyr_types.h to inst/include/dplyr_types.h 45 | 46 | ```{r} 47 | "{src => inst/include}/dplyr_types.h" 48 | ``` 49 | 50 | # Processing 51 | 52 | 0. Preprocess name to have `{` and `}`. 53 | 1. take left title (vignettes / None) 54 | 2. take right title (file name) 55 | 3. Set left expression in parenthesis as old, right one as new. 56 | 4. Paste left title with left expr and right expr and add right title 57 | 58 | --------------------------------------------------------------------------------