git2r/0000755000176200001440000000000014705305562011310 5ustar liggesusersgit2r/tests/0000755000176200001440000000000014530613147012447 5ustar liggesusersgit2r/tests/clone_checkout.R0000644000176200001440000000465114530613147015565 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create 2 directories in tempdir path_src <- tempfile(pattern = "git2r-") path_tgt <- tempfile(pattern = "git2r-") dir.create(path_tgt) dir.create(path_src) ## Initialize a repository repo_src <- init(path_src) config(repo_src, user.name = "Alice", user.email = "alice@example.org") ## Add commit to repo filename <- "test.txt" writeLines("Hello world", con = file.path(path_src, filename)) add(repo_src, "test.txt") commit_src <- commit(repo_src, "Commit message") ## Check checkout argument tools::assertError(clone(path_src, path_tgt, checkout = c(FALSE, TRUE))) tools::assertError(clone(path_src, path_tgt, checkout = 1)) tools::assertError(clone(path_src, path_tgt, checkout = 1L)) tools::assertError(clone(path_src, path_tgt, checkout = "test")) ## Clone source to target repository without checking out any files repo_tgt <- clone(path_src, path_tgt, checkout = FALSE) ## List files in the repositores stopifnot(identical(list.files(path_src), filename)) stopifnot(identical(list.files(path_tgt), character(0))) ## Compare commits stopifnot(identical(length(commits(repo_tgt)), 1L)) commit_tgt <- last_commit(repo_tgt) stopifnot(identical(sha(last_commit(path_tgt)), sha(commit_tgt))) stopifnot(identical(sha(commit_src), sha(commit_tgt))) stopifnot(identical(commit_src$author, commit_tgt$author)) stopifnot(identical(commit_src$committer, commit_tgt$committer)) stopifnot(identical(commit_src$summary, commit_tgt$summary)) stopifnot(identical(commit_src$message, commit_tgt$message)) stopifnot(!identical(commit_src$repo, commit_tgt$repo)) ## Cleanup unlink(path_tgt, recursive = TRUE) unlink(path_src, recursive = TRUE) git2r/tests/branch.R0000644000176200001440000001232314530613147014030 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path, branch = "main") config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file writeLines("Hello world!", file.path(path, "test.txt")) ## add and commit add(repo, "test.txt") commit_1 <- commit(repo, "Commit message") ## Check branch stopifnot(identical(length(branches(repo)), 1L)) stopifnot(identical(is_head(branches(repo)[[1]]), TRUE)) stopifnot(identical(is_local(branches(repo)[[1]]), TRUE)) stopifnot(identical(branches(repo)[[1]]$name, "main")) stopifnot(identical(branches(repo)[[1]], repository_head(repo))) stopifnot(identical(branches(repo)$main, repository_head(repo))) ## Check branch argument res <- tools::assertError(is_local(1)) stopifnot(length(grep("argument 'branch' must be a 'git_branch' object", res[[1]]$message)) > 0) ## Check branch name argument res <- tools::assertError(branch_set_upstream()) stopifnot(length(grep("Missing argument name", res[[1]]$message)) > 0) ## Print branch b <- repository_head(repo) stopifnot(identical(print(b), b)) ## Create a branch b <- branch_create(commit_1, name = "test") stopifnot(identical(b$name, "test")) stopifnot(identical(b$type, 1L)) stopifnot(identical(sha(b), branch_target(b))) stopifnot(identical(length(branches(repo)), 2L)) stopifnot(identical(branch_target(branches(repo)[[1]]), branch_target(branches(repo)[[2]]))) ## Check is_branch stopifnot(identical(is_branch(b), TRUE)) stopifnot(identical(is_branch(5), FALSE)) ## Add one more commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) add(repo, "test.txt") commit_2 <- commit(repo, "Another commit message") ## Now the first branch should have moved on stopifnot(!identical(branch_target(branches(repo)[[1]]), branch_target(branches(repo)[[2]]))) ## Create a branch with the same name should fail tools::assertError(branch_create(commit_2, name = "test")) ## Force it and check the branches are identical again b <- branch_create(commit_2, name = "test", force = TRUE) stopifnot(identical(branch_target(branches(repo)[[1]]), branch_target(branches(repo)[[2]]))) ## Test arguments res <- tools::assertError(.Call(git2r:::git2r_branch_delete, NULL)) stopifnot(length(grep("'branch' must be an S3 class git_branch", res[[1]]$message)) > 0) res <- tools::assertError(.Call(git2r:::git2r_branch_delete, 3)) stopifnot(length(grep("'branch' must be an S3 class git_branch", res[[1]]$message)) > 0) res <- tools::assertError(.Call(git2r:::git2r_branch_delete, repo)) stopifnot(length(grep("'branch' must be an S3 class git_branch", res[[1]]$message)) > 0) b_tmp <- b b_tmp$name <- NA_character_ res <- tools::assertError(.Call(git2r:::git2r_branch_delete, b_tmp)) stopifnot(length(grep("'branch' must be an S3 class git_branch", res[[1]]$message)) > 0) b_tmp <- b b_tmp$type <- NA_integer_ res <- tools::assertError(.Call(git2r:::git2r_branch_delete, b_tmp)) stopifnot(length(grep("'branch' must be an S3 class git_branch", res[[1]]$message)) > 0) b_tmp$type <- 3L res <- tools::assertError(.Call(git2r:::git2r_branch_delete, b_tmp)) stopifnot(length(grep("'branch' must be an S3 class git_branch", res[[1]]$message)) > 0) ## Delete branch branch_delete(b) stopifnot(identical(length(branches(repo)), 1L)) ## Add one more commit writeLines(c("Hello world!", "HELLO WORLD!", "hello world"), file.path(path, "test.txt")) add(repo, "test.txt") commit_3 <- commit(repo, "Another third commit message") ## Create and test renaming of branches b_1 <- branch_create(commit_1, name = "test-1") b_2 <- branch_create(commit_2, name = "test-2") b_3 <- branch_create(commit_3, name = "test-3") stopifnot(identical(length(branches(repo)), 4L)) b_1 <- branch_rename(b_1, name = "test-1-new-name") stopifnot(identical(length(branches(repo)), 4L)) stopifnot(identical(b_1$name, "test-1-new-name")) tools::assertError(branch_rename(b_1, name = "test-2")) branch_rename(b_1, name = "test-2", force = TRUE) stopifnot(identical(length(branches(repo)), 3L)) ## Check branches method with missing repo argument wd <- setwd(path) stopifnot(identical(length(branches()), 3L)) if (!is.null(wd)) setwd(wd) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/pull.R0000644000176200001440000001150014530613147013543 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create directories for repositories in tempdir path_bare <- tempfile(pattern = "git2r-") path_repo_1 <- tempfile(pattern = "git2r-") path_repo_2 <- tempfile(pattern = "git2r-") dir.create(path_bare) dir.create(path_repo_1) dir.create(path_repo_2) ## Create bare repository bare_repo <- init(path_bare, bare = TRUE) ## Clone to repo 1 repo_1 <- clone(path_bare, path_repo_1) config(repo_1, user.name = "Alice", user.email = "alice@example.org") ## Add changes to repo 1 and push to bare writeLines("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", con = file.path(path_repo_1, "test-1.txt")) add(repo_1, "test-1.txt") commit_1 <- commit(repo_1, "First commit message") branch_name <- branches(repo_1)[[1]]$name push(repo_1, "origin", paste0("refs/heads/", branch_name)) ## Clone to repo 2 repo_2 <- clone(path_bare, path_repo_2) config(repo_2, user.name = "Bob", user.email = "bob@example.org") ## Add more changes to repo 1 and push to bare writeLines(c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path_repo_1, "test-1.txt")) add(repo_1, "test-1.txt") commit_2 <- commit(repo_1, "Second commit message") push(repo_1, "origin", paste0("refs/heads/", branch_name)) ## Pull changes to repo_2 pull(repo_2) stopifnot(identical(length(commits(repo_2)), 2L)) ## Check remote url of repo_2 stopifnot(identical( branch_remote_url(branch_get_upstream(repository_head(repo_2))), path_bare)) ## Unset remote remote tracking branch branch_set_upstream(repository_head(repo_2), NULL) stopifnot(is.null(branch_get_upstream(repository_head(repo_2)))) tools::assertError(pull(repo_2)) tools::assertError(branch_set_upstream(repository_head(repo_2), NULL)) ## Add more changes to repo 1 and push to bare writeLines( c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", "minim veniam, quis nostrud exercitation ullamco laboris nisi ut"), con = file.path(path_repo_1, "test-1.txt")) add(repo_1, "test-1.txt") commit_3 <- commit(repo_1, "Third commit message") push(repo_1) ## Set remote tracking branch branch_set_upstream(repository_head(repo_2), paste0("origin/", branch_name)) stopifnot(identical( branch_remote_url(branch_get_upstream(repository_head(repo_2))), path_bare)) ## Pull changes to repo_2 pull(repo_2) stopifnot(identical(length(commits(repo_2)), 3L)) ## Check references in repo_1 and repo_2. Must clear the repo item ## since the repositories have different paths. stopifnot(identical(length(references(repo_1)), 2L)) ref_1 <- references(repo_1) lapply(seq_len(length(ref_1)), function(i) { ref_1[[i]]$repo <<- NULL }) ref_2 <- references(repo_2) lapply(seq_len(length(ref_2)), function(i) { ref_2[[i]]$repo <<- NULL }) name <- paste0("refs/heads/", branch_name) stopifnot(identical(ref_1[[name]], ref_2[[name]])) name <- paste0("refs/remotes/", branch_name) stopifnot(identical(ref_1[[name]], ref_2[[name]])) ref_1 <- references(repo_1)[[paste0("refs/heads/", branch_name)]] stopifnot(identical(ref_1$name, paste0("refs/heads/", branch_name))) stopifnot(identical(ref_1$type, 1L)) stopifnot(identical(sha(ref_1), sha(commit_3))) stopifnot(identical(ref_1$target, NA_character_)) stopifnot(identical(ref_1$shorthand, branch_name)) ref_2 <- references(repo_1)[[paste0("refs/remotes/origin/", branch_name)]] stopifnot(identical(ref_2$name, paste0("refs/remotes/origin/", branch_name))) stopifnot(identical(ref_2$type, 1L)) stopifnot(identical(sha(ref_2), sha(commit_3))) stopifnot(identical(ref_2$target, NA_character_)) stopifnot(identical(ref_2$shorthand, paste0("origin/", branch_name))) ## Check references with missing repo argument wd <- setwd(path_repo_1) stopifnot(identical(length(references()), 2L)) if (!is.null(wd)) setwd(wd) ## Cleanup unlink(path_bare, recursive = TRUE) unlink(path_repo_1, recursive = TRUE) unlink(path_repo_2, recursive = TRUE) git2r/tests/index.R0000644000176200001440000001031614530613147013702 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) source("util/check.R") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create directories dir.create(file.path(path, "sub-folder")); dir.create(file.path(path, "sub-folder", "sub-sub-folder")); ## Create files writeLines("Hello world!", file.path(path, "file-1.txt")) writeLines("Hello world!", file.path(path, "sub-folder", "file-2.txt")) writeLines("Hello world!", file.path(path, "sub-folder", "file-3.txt")) writeLines("Hello world!", file.path(path, "sub-folder", "sub-sub-folder", "file-4.txt")) writeLines("Hello world!", file.path(path, "sub-folder", "sub-sub-folder", "file-5.txt")) ## Add add(repo, "file-1.txt") status_exp <- structure(list(staged = list(new = "file-1.txt"), unstaged = empty_named_list(), untracked = list(untracked = "sub-folder/")), class = "git_status") status_obs <- status(repo) stopifnot(identical(status_obs, status_exp)) ## Index remove by path index_remove_bypath(repo, "file-1.txt") status_exp <- structure(list(staged = empty_named_list(), unstaged = empty_named_list(), untracked = list(untracked = "file-1.txt", untracked = "sub-folder/")), class = "git_status") status_obs <- status(repo) stopifnot(identical(status_obs, status_exp)) ## Add add(repo, "sub-folder") status_exp <- structure(list(staged = list( new = "sub-folder/file-2.txt", new = "sub-folder/file-3.txt", new = "sub-folder/sub-sub-folder/file-4.txt", new = "sub-folder/sub-sub-folder/file-5.txt"), unstaged = empty_named_list(), untracked = list(untracked = "file-1.txt")), class = "git_status") status_obs <- status(repo) stopifnot(identical(status_obs, status_exp)) ## Commit commit(repo, "First commit message") ## It should fail to remove non-existing, untracked and ignored files tools::assertError(rm_file(repo, c("file-1.txt", "file-2.txt"))) tools::assertError(rm_file(repo, c("file-1.txt", ""))) tools::assertError(rm_file(repo, c("file-1.txt"))) writeLines("/file-1.txt", file.path(path, ".gitignore")) tools::assertError(rm_file(repo, "file-1.txt")) ## It should fail to remove files with staged changes file.remove(file.path(path, ".gitignore")) add(repo, "file-1.txt") tools::assertError(rm_file(repo, "file-1.txt")) ## It should fail to remove files with unstaged changes commit(repo, "Second commit message") writeLines(c("Hello world!", "Hello world!"), file.path(path, "file-1.txt")) tools::assertError(rm_file(repo, "file-1.txt")) ## Remove file add(repo, "file-1.txt") commit(repo, "Third commit message") rm_file(repo, "file-1.txt") status_exp <- structure(list(staged = list(deleted = "file-1.txt"), unstaged = empty_named_list(), untracked = empty_named_list()), class = "git_status") status_obs <- status(repo) stopifnot(identical(status_obs, status_exp)) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/signature.R0000644000176200001440000000227514530613147014601 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Check printing of a class git_signature when <- structure(list(time = 1395567947, offset = 60), class = "git_time") signature <- structure(list(name = "Alice", email = "alice@example.org", when = when), class = "git_signature") stopifnot(identical(print(signature), signature)) git2r/tests/repository.R0000644000176200001440000000715214530613147015016 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) source("util/check.R") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## is_bare: "Invalid repository" tools::assertError(is_bare(new("git_repository"))) ## is_empty: "Invalid repository" tools::assertError(is_empty(new("git_repository"))) ## Check that open an invalid repository fails tools::assertError(repository(path)) tools::assertError(repository(path, discover = FALSE)) ## Check that it fails to open/init a repository with a path to a ## file. writeLines("test", file.path(path, "test.txt")) tools::assertError(repository(file.path(path, "test.txt"), discover = FALSE)) tools::assertError(init(file.path(path, "test.txt"))) unlink(file.path(path, "test.txt")) ## Initialize a repository repo <- init(path) stopifnot(identical(print(repo), repo)) ## Check the state of the repository stopifnot(identical(is_bare(repo), FALSE)) stopifnot(identical(is_empty(repo), TRUE)) stopifnot(identical(is_shallow(repo), FALSE)) stopifnot(identical(branches(repo), empty_named_list())) stopifnot(identical(references(repo), empty_named_list())) stopifnot(identical(commits(repo), list())) stopifnot(identical(repository_head(repo), NULL)) # check that we can find repository from a path wd <- sub(paste0("[", .Platform$file.sep, "]$"), "", workdir(repo)) writeLines("test file", con = file.path(wd, "myfile.txt")) stopifnot(identical(discover_repository(file.path(wd, "myfile.txt")), file.path(wd, ".git"))) stopifnot(identical(discover_repository(file.path(wd, "doesntexist.txt")), NULL)) # Check that we can use ceiling in discover repostiory dir.create(file.path(wd, "temp")) stopifnot(identical(discover_repository(file.path(wd, "temp"), 0), NULL)) stopifnot(identical(discover_repository(file.path(wd, "temp"), 1), file.path(wd, ".git"))) tools::assertError(discover_repository(file.path(wd, "temp"), 2)) ## Check that lookup with a sha of less than 4 characters or more than ## 40 characters fail. tools::assertError(lookup(repo, paste0(rep("a", 3), collapse = ""))) tools::assertError(lookup(repo, paste0(rep("a", 41), collapse = ""))) ## Check in_repository stopifnot(identical(in_repository(path), TRUE)) ## Check: ## - in_repository method with missing path argument ## - repository method with missing path argument ## - workdir method with missing path argument ## - is_empty method with missing repo argument ## - is_shallow method with missing repo argument wd <- setwd(path) stopifnot(identical(in_repository(), TRUE)) stopifnot(identical(workdir(repository(path)), workdir(repository()))) stopifnot(identical(workdir(repository(path)), workdir())) stopifnot(identical(is_empty(), TRUE)) stopifnot(identical(is_shallow(), FALSE)) if (!is.null(wd)) setwd(wd) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/bare_repository.R0000644000176200001440000000246314530613147016007 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a bare repository repo <- init(path, bare = TRUE) ## Check that the state of the repository stopifnot(identical(is_bare(repo), TRUE)) stopifnot(identical(is_empty(repo), TRUE)) ## Check that workdir is NULL for a bare repository stopifnot(is.null(workdir(repo))) ## Check with missing repo argument setwd(path) stopifnot(identical(is_bare(), TRUE)) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/add-force.R0000644000176200001440000000476714530613147014434 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) source("util/check.R") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a '.gitignore' file writeLines("test.txt", file.path(path, ".gitignore")) add(repo, ".gitignore") commit(repo, "First commit message") ## Create a file writeLines("Hello world!", file.path(path, "test.txt")) ## Check status s_1 <- structure(list(staged = empty_named_list(), unstaged = empty_named_list(), untracked = empty_named_list(), ignored = list(ignored = "test.txt")), class = "git_status") stopifnot(identical(status(repo, ignored = TRUE), s_1)) ## The file is ignored and should not be added add(repo, "test.txt") stopifnot(identical(status(repo, ignored = TRUE), s_1)) ## The file is ignored but should be added with force s_2 <- structure(list(staged = list(new = "test.txt"), unstaged = empty_named_list(), untracked = empty_named_list(), ignored = empty_named_list()), class = "git_status") add(repo, "test.txt", force = TRUE) stopifnot(identical(status(repo, ignored = TRUE), s_2)) ## Commit and check status s_3 <- structure(list(staged = empty_named_list(), unstaged = empty_named_list(), untracked = empty_named_list(), ignored = empty_named_list()), class = "git_status") commit(repo, "Second commit message") stopifnot(identical(status(repo, ignored = TRUE), s_3)) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/pre-process-path.R0000644000176200001440000001143414530613147015771 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) source("util/check.R") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) setwd(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Test to add file with a leading './' writeLines("foo-1", file.path(path, "foo-1")) add(repo, "./foo-1") status_exp <- structure(list(staged = list(new = "foo-1"), unstaged = empty_named_list(), untracked = empty_named_list()), class = "git_status") status_obs <- status(repo) str(status_exp) str(status_obs) stopifnot(identical(status_obs, status_exp)) ## Test to add file in sub-folder with sub-folder as working directory writeLines("foo-2", file.path(path, "foo-2")) dir.create(file.path(path, "foo_dir")) writeLines("foo-2", file.path(path, "foo_dir/foo-2")) setwd("./foo_dir") add(repo, "foo-2") status_exp <- structure(list(staged = list(new = "foo-1", new = "foo_dir/foo-2"), unstaged = empty_named_list(), untracked = list(untracked = "foo-2")), class = "git_status") status_obs <- status(repo) str(status_exp) str(status_obs) stopifnot(identical(status_obs, status_exp)) ## Test glob expansion setwd(tempdir()) dir.create(file.path(path, "glob_dir")) writeLines("a", file.path(path, "glob_dir/a.txt")) writeLines("b", file.path(path, "glob_dir/b.txt")) writeLines("c", file.path(path, "glob_dir/c.txt")) writeLines("d", file.path(path, "glob_dir/d.md")) add(repo, "glob_dir/*txt") status_exp <- structure(list(staged = list(new = "foo-1", new = "foo_dir/foo-2", new = "glob_dir/a.txt", new = "glob_dir/b.txt", new = "glob_dir/c.txt"), unstaged = empty_named_list(), untracked = list(untracked = "foo-2", untracked = "glob_dir/d.md")), class = "git_status") status_obs <- status(repo) str(status_exp) str(status_obs) stopifnot(identical(status_obs, status_exp)) ## Test glob expansion with relative path setwd(path) add(repo, "./glob_dir/*md") status_exp <- structure(list(staged = list(new = "foo-1", new = "foo_dir/foo-2", new = "glob_dir/a.txt", new = "glob_dir/b.txt", new = "glob_dir/c.txt", new = "glob_dir/d.md"), unstaged = empty_named_list(), untracked = list(untracked = "foo-2")), class = "git_status") status_obs <- status(repo) str(status_exp) str(status_obs) stopifnot(identical(status_obs, status_exp)) ## Test to add file in root of workdir when the file also exists in ## current workdir. setwd(tempdir()) writeLines("e", file.path(path, "e.txt")) writeLines("e", file.path(tempdir(), "e.txt")) add(repo, "e.txt") status_exp <- structure(list(staged = list(new = "e.txt", new = "foo-1", new = "foo_dir/foo-2", new = "glob_dir/a.txt", new = "glob_dir/b.txt", new = "glob_dir/c.txt", new = "glob_dir/d.md"), unstaged = empty_named_list(), untracked = list(untracked = "foo-2")), class = "git_status") status_obs <- status(repo) str(status_exp) str(status_obs) stopifnot(identical(status_obs, status_exp)) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/merge_named_branch.R0000644000176200001440000000766314530613147016366 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) source("util/check.R") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path, branch = "main") config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit writeLines("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", con = file.path(path, "test.txt")) add(repo, "test.txt") commit_1 <- commit(repo, "Commit message 1") ## Create first branch, checkout, add file and commit checkout(repo, "branch1", create = TRUE) writeLines("Branch 1", file.path(path, "branch-1.txt")) add(repo, "branch-1.txt") commit_2 <- commit(repo, "Commit message branch 1") ## Create second branch, checkout, add file and commit b_2 <- branch_create(commit_1, "branch2") checkout(b_2) writeLines("Branch 2", file.path(path, "branch-2.txt")) add(repo, "branch-2.txt") commit_3 <- commit(repo, "Commit message branch 2") writeLines(c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path, "test.txt")) add(repo, "test.txt") commit_4 <- commit(repo, "Second commit message branch 2") ## Check that merge base equals commit_1 stopifnot(identical(merge_base(commit_2, commit_3), commit_1)) ## Checkout main b <- branches(repo) checkout(b[sapply(b, "[", "name") == "main"][[1]], force = TRUE) ## Merge branch 1 m_1 <- merge(repo, "branch1") stopifnot(identical(m_1$fast_forward, TRUE)) stopifnot(identical(m_1$conflicts, FALSE)) stopifnot(identical(sha(m_1), NA_character_)) ## Merge branch 2 m_2 <- merge(path, "branch2") stopifnot(identical(m_2$fast_forward, FALSE)) stopifnot(identical(m_2$conflicts, FALSE)) stopifnot(identical(sha(m_2), sha(commits(repo)[[1]]))) ## Create third branch, checkout, change file and commit checkout(repo, "branch3", create = TRUE) writeLines(c("Lorem ipsum dolor amet sit, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Commit message branch 3") ## Checkout main and create a change that creates a merge conflict checkout(repo, "main", force = TRUE) writeLines(c("Lorem ipsum dolor sit amet, adipisicing consectetur elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Some commit message branch 1") ## Merge branch 3 m_3 <- merge(repo, "branch3") stopifnot(identical(m_3$up_to_date, FALSE)) stopifnot(identical(m_3$fast_forward, FALSE)) stopifnot(identical(m_3$conflicts, TRUE)) stopifnot(identical(sha(m_3), NA_character_)) ## Check status; Expect to have one unstaged unmerged conflict. stopifnot(identical(status(repo), structure(list(staged = empty_named_list(), unstaged = list(conflicted = "test.txt"), untracked = empty_named_list()), class = "git_status"))) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/tag.R0000644000176200001440000000545714530613147013360 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) source("util/check.R") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file writeLines("Hello world!", file.path(path, "test.txt")) ## add and commit add(repo, "test.txt") commit(repo, "Commit message") ## Check tags, no tag added stopifnot(identical(tags(repo), empty_named_list())) ## Create tag new_tag <- tag(repo, "Tagname", "Tag message") stopifnot(identical(print(new_tag), new_tag)) summary(new_tag) ## Check tag stopifnot(identical(lookup(repo, sha(new_tag)), new_tag)) stopifnot(identical(new_tag$name, "Tagname")) stopifnot(identical(new_tag$message, "Tag message")) stopifnot(identical(new_tag$tagger$name, "Alice")) stopifnot(identical(new_tag$tagger$email, "alice@example.org")) stopifnot(identical(length(tags(repo)), 1L)) stopifnot(identical(tags(repo)[[1]]$name, "Tagname")) stopifnot(identical(tags(repo)[[1]]$message, "Tag message")) stopifnot(identical(tags(repo)[[1]]$tagger$name, "Alice")) stopifnot(identical(tags(repo)[[1]]$tagger$email, "alice@example.org")) ## Check objects in object database stopifnot(identical(table(odb_objects(repo)$type), structure(c(1L, 1L, 1L, 1L), .Dim = 4L, .Dimnames = structure(list( c("blob", "commit", "tag", "tree")), .Names = ""), class = "table"))) ## Delete tag tag_delete(new_tag) stopifnot(identical(length(tags(repo)), 0L)) ## Create tag with session info tag(repo, "Tagname", "Tag message", session = TRUE) stopifnot(grep("git2r", tags(repo)[[1]]$message) > 0) ## Check tags method with default repo argument wd <- setwd(path) stopifnot(identical(length(tags()), 1L)) tag_delete(name = "Tagname") stopifnot(identical(length(tags()), 0L)) if (!is.null(wd)) setwd(wd) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/util/0000755000176200001440000000000014523621065013424 5ustar liggesusersgit2r/tests/util/check.R0000644000176200001440000000215314523621065014625 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2019 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. empty_named_list <- function() { structure(list(), .Names = character(0)) } ## Raise an error if the error message doesn't match. check_error <- function(current, target, exact = FALSE) { if (isTRUE(exact)) { stopifnot(identical(current[[1]]$message, target)) } else { stopifnot(length(grep(target, current[[1]]$message)) > 0) } invisible(NULL) } git2r/tests/checkout_commit.R0000644000176200001440000000342514530613147015753 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create first commit writeLines("Hello world!", file.path(path, "test-1.txt")) add(repo, "test-1.txt") commit_1 <- commit(repo, "First commit message") ## Create and checkout dev branch in repo checkout(repo, "dev", create = TRUE) ## Create second commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test-2.txt")) add(repo, "test-2.txt") commit_2 <- commit(repo, "Second commit message") ## Check files stopifnot(identical(list.files(path), c("test-1.txt", "test-2.txt"))) ## Checkout commit_1 and check files checkout(commit_1) stopifnot(identical(list.files(path), "test-1.txt")) ## Checkout commit_2 and check files checkout(commit_2) stopifnot(identical(list.files(path), c("test-1.txt", "test-2.txt"))) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/graph.R0000644000176200001440000000352714530613147013702 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file and commit writeLines("Hello world!", file.path(path, "test.txt")) add(repo, "test.txt") commit_1 <- commit(repo, "First commit message") tag_1 <- tag(repo, "Tagname1", "Tag message 1") ## Change file and commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) add(repo, "test.txt") commit_2 <- commit(repo, "Second commit message") tag_2 <- tag(repo, "Tagname2", "Tag message 2") ## Check ahead behind stopifnot(identical(ahead_behind(commit_1, commit_2), c(0L, 1L))) stopifnot(identical(ahead_behind(tag_1, tag_2), c(0L, 1L))) stopifnot(identical(ahead_behind(tag_2, tag_1), c(1L, 0L))) stopifnot(identical(ahead_behind(commit_1, branches(repo)[[1]]), c(0L, 1L))) stopifnot(identical(ahead_behind(branches(repo)[[1]], commit_1), c(1L, 0L))) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/odb_blobs.R0000644000176200001440000000437014530613147014523 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@@example.org") ## Create a file, add and commit writeLines("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", con = file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Commit message 1") ## Change file and commit writeLines(c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Commit message 2") ## Commit same content under different name in a sub-directory dir.create(file.path(path, "sub-directory")) file.copy(file.path(path, "test.txt"), file.path(path, "sub-directory", "copy.txt")) add(repo, "sub-directory/copy.txt") commit(repo, "Commit message 3") ## List blobs b <- odb_blobs(repo) ## Order the data.frame before checking b <- b[order(b$name), ] ## Check blobs stopifnot(identical(nrow(b), 3L)) stopifnot(identical( colnames(b), c("sha", "path", "name", "len", "commit", "author", "when"))) stopifnot(identical(b$path, c("sub-directory", "", ""))) stopifnot(identical(b$name, c("copy.txt", "test.txt", "test.txt"))) stopifnot(identical(b$author, c("Alice", "Alice", "Alice"))) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/checkout_tag.R0000644000176200001440000000373014530613147015235 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create first commit writeLines("Hello world!", file.path(path, "test-1.txt")) add(repo, "test-1.txt") commit_1 <- commit(repo, "First commit message") tag_1 <- tag(repo, "Tag1", "First tag message") ## Create and checkout dev branch in repo checkout(repo, "dev", create = TRUE) ## Create second commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test-2.txt")) add(repo, "test-2.txt") commit_2 <- commit(repo, "Second commit message") tag_2 <- tag(repo, "Tag2", "Second tag message") ## Check files stopifnot(identical(list.files(path), c("test-1.txt", "test-2.txt"))) ## Checkout tag_1 and check files checkout(tag_1) stopifnot(identical(list.files(path), "test-1.txt")) ## Checkout tag_2 and check files checkout(tag_2) stopifnot(identical(list.files(path), c("test-1.txt", "test-2.txt"))) ## Checkout "Tag1" and check files checkout(repo, "Tag1") stopifnot(identical(list.files(path), "test-1.txt")) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/remove.R0000644000176200001440000000273114530613147014072 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Add files invisible(lapply(file.path(path, letters[1:4]), writeLines, text = "")) add(repo, letters) commit(repo, "init") ## Remove one file rm_file(repo, letters[1]) commit(repo, "remove") ## Remove two files. Don't raise warnings withCallingHandlers(rm_file(repo, letters[2:3]), warning = function(w) stop(w)) ## Remove one file using the absolute path to the file. rm_file(repo, file.path(path, letters[4])) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/reflog.R0000644000176200001440000000345114530613147014053 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Check that reflog is empty stopifnot(identical(reflog(repo), structure(list(), class = "git_reflog"))) ## Create a file writeLines("Hello world!", file.path(path, "test.txt")) ## add and commit add(repo, "test.txt") commit_1 <- commit(repo, "Commit message") ## Check that reflog is not empry stopifnot(identical(length(reflog(repo)), 1L)) reflog_entry <- reflog(repo)[[1]] stopifnot(identical(sha(reflog_entry), sha(commit_1))) stopifnot(identical(reflog_entry$refname, "HEAD")) stopifnot(identical(reflog_entry$index, 0L)) stopifnot(identical(reflog_entry$committer$email, "alice@example.org")) stopifnot(identical(reflog_entry$message, "commit (initial): Commit message")) ## Check printing r <- reflog(repo) stopifnot(identical(print(r), r)) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/revparse.R0000644000176200001440000000305014530613147014417 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file writeLines("Hello world!", file.path(path, "test.txt")) ## Add and commit add(repo, "test.txt") commit_1 <- commit(repo, "First commit message") tools::assertError(revparse_single(repo, "HEAD^")) ## Add another commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Second commit message") stopifnot(identical(revparse_single(repo, "HEAD^"), commit_1)) stopifnot(is_blob(revparse_single(repo, "HEAD:test.txt"))) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/checkout.R0000644000176200001440000000730514530613147014404 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path, branch = "main") config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create first commit writeLines("Hello world!", file.path(path, "test.txt")) add(repo, "test.txt") commit_1 <- commit(repo, "First commit message") ## Edit file and checkout writeLines(c("Hello world!", "Hello world!"), file.path(path, "test.txt")) status_exp_1 <- structure(list(staged = structure(list(), .Names = character(0)), unstaged = structure(list(modified = "test.txt"), .Names = "modified"), untracked = structure(list(), .Names = character(0))), .Names = c("staged", "unstaged", "untracked"), class = "git_status") status_obs_1 <- status(repo) str(status_exp_1) str(status_obs_1) stopifnot(identical(status_obs_1, status_exp_1)) checkout(repo, path = "test.txt") status_exp_2 <- structure(list(staged = structure(list(), .Names = character(0)), unstaged = structure(list(), .Names = character(0)), untracked = structure(list(), .Names = character(0))), .Names = c("staged", "unstaged", "untracked"), class = "git_status") status_obs_2 <- status(repo) str(status_exp_2) str(status_obs_2) stopifnot(identical(status_obs_2, status_exp_2)) ## Create second commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) add(repo, "test.txt") commit_2 <- commit(repo, "Second commit message") tag(repo, "commit_2", "Tag message") ## Create third commit writeLines(c("Hello world!", "HELLO WORLD!", "HeLlO wOrLd!"), file.path(path, "test.txt")) add(repo, "test.txt") commit_3 <- commit(repo, "Third commit message") ## Check HEAD stopifnot(identical(is_detached(repo), FALSE)) stopifnot(identical(repository_head(repo)$name, "main")) ## Check show and summary repo summary(repo) ## Checkout first commit checkout(commit_1, TRUE) stopifnot(identical(is_detached(repo), TRUE)) stopifnot(identical(repository_head(repo), commit_1)) stopifnot(identical(readLines(file.path(path, "test.txt")), "Hello world!")) ## Check show and summary repo summary(repo) ## Checkout tag checkout(tags(repo)[[1]], TRUE) stopifnot(identical(is_detached(repo), TRUE)) stopifnot(identical(readLines(file.path(path, "test.txt")), c("Hello world!", "HELLO WORLD!"))) ## Check is_detached with missing repo argument wd <- setwd(path) stopifnot(identical(is_detached(), TRUE)) if (!is.null(wd)) setwd(wd) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/libgit2.R0000644000176200001440000000252214530613147014127 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() stopifnot(identical(names(libgit2_features()), c("threads", "https", "ssh"))) stopifnot(identical(names(libgit2_version()), c("major", "minor", "rev"))) tools::assertError(ssl_cert_locations()) if (identical(Sys.getenv("R_COVR"), "true")) { if (isTRUE(libgit2_features()$https)) { ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) stopifnot(is.null(ssl_cert_locations(path = path))) unlink(path) } } git2r/tests/invalid-conf-var.R0000644000176200001440000000331714530613147015735 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) ## Config repository config(repo, user.name = "Alice") ## Let's set one valid and one with variable with invalid format res <- tools::assertWarning(config(repo, user.email = "alice@example.org", lol = "wut")) stopifnot(length(grep("Variable was not in a valid format: 'lol'", res[[1]]$message)) > 0) cfg_exp <- structure(list(user.name = "Alice", user.email = "alice@example.org", "NA" = NULL), .Names = c("user.name", "user.email", NA)) cfg_obs <- config(repo)$local cfg_obs <- cfg_obs[c("user.name", "user.email", "lol")] stopifnot(identical(cfg_obs, cfg_exp)) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/refspec.R0000644000176200001440000000372714530613147014232 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create directories for repositories in tempdir path_bare <- tempfile(pattern = "git2r-") path_repo <- tempfile(pattern = "git2r-") dir.create(path_bare) dir.create(path_repo) ## Create bare repository bare_repo <- init(path_bare, bare = TRUE) ## Clone to repo repo <- clone(path_bare, path_repo) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Add changes to repo writeLines("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", con = file.path(path_repo, "test.txt")) add(repo, "test.txt") commit_1 <- commit(repo, "First commit message") ## Add more changes to repo writeLines(c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path_repo, "test.txt")) add(repo, "test.txt") commit_2 <- commit(repo, "Second commit message") ## Check remote stopifnot(identical( git2r:::get_refspec(repo, spec = "master")$remote, "origin")) ## Detach checkout(commit_1) tools::assertError(git2r:::get_refspec(repo)) ## Cleanup unlink(path_bare, recursive = TRUE) unlink(path_repo, recursive = TRUE) git2r/tests/push-force.R0000644000176200001440000000574614530613147014661 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create directories for repositories in tempdir path_bare <- tempfile(pattern = "git2r-") path_repo_1 <- tempfile(pattern = "git2r-") path_repo_2 <- tempfile(pattern = "git2r-") dir.create(path_bare) dir.create(path_repo_1) dir.create(path_repo_2) ## Create bare repository bare_repo <- init(path_bare, bare = TRUE) ## Clone to repo 1 repo_1 <- clone(path_bare, path_repo_1) config(repo_1, user.name = "Alice", user.email = "alice@example.org") ## Add changes to repo 1 and push to bare writeLines("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", con = file.path(path_repo_1, "test-1.txt")) add(repo_1, "test-1.txt") commit_1 <- commit(repo_1, "First commit message") branch_name <- branches(repo_1)[[1]]$name push(repo_1, "origin", paste0("refs/heads/", branch_name)) ## Clone to repo 2 repo_2 <- clone(path_bare, path_repo_2) config(repo_2, user.name = "Bob", user.email = "bob@example.org") ## Add more changes to repo 1 and push to bare writeLines(c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path_repo_1, "test-1.txt")) add(repo_1, "test-1.txt") commit_2 <- commit(repo_1, "Second commit message") push(repo_1, "origin", paste0("refs/heads/", branch_name)) ## Add changes to repo 2 and push to bare writeLines( c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", "minim veniam, quis nostrud exercitation ullamco laboris nisi ut"), con = file.path(path_repo_2, "test-1.txt")) add(repo_2, "test-1.txt") commit_3 <- commit(repo_2, "Third commit message") ## We are behind, so this should fail tools::assertError(push(repo_2)) ## Push with force = TRUE push(repo_2, force = TRUE) ## Check commits stopifnot(identical(length(commits(bare_repo)), 2L)) stopifnot(identical(sha(commits(repo_2)[[1]]), sha(commits(bare_repo)[[1]]))) stopifnot(identical(sha(commits(repo_2)[[2]]), sha(commits(bare_repo)[[2]]))) ## Cleanup unlink(path_bare, recursive = TRUE) unlink(path_repo_1, recursive = TRUE) unlink(path_repo_2, recursive = TRUE) git2r/tests/clone_branch.R0000644000176200001440000000556614530613147015223 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create directories for repositories in tempdir path_bare <- tempfile(pattern = "git2r-") path_repo_1 <- tempfile(pattern = "git2r-") path_repo_2 <- tempfile(pattern = "git2r-") dir.create(path_bare) dir.create(path_repo_1) dir.create(path_repo_2) ## Create bare repository bare_repo <- init(path_bare, bare = TRUE) ## Clone to repo 1 repo_1 <- clone(path_bare, path_repo_1) config(repo_1, user.name = "Alice", user.email = "alice@example.org") ## Add changes to repo 1 writeLines("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", con = file.path(path_repo_1, "test-1.txt")) add(repo_1, "test-1.txt") commit_1 <- commit(repo_1, "First commit message") branch_name <- branches(repo_1)[[1]]$name ## Create 'dev' branch checkout(branch_create(commit_1, name = "dev")) ## Add more changes to repo 1 writeLines(c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path_repo_1, "test-1.txt")) add(repo_1, "test-1.txt") commit(repo_1, "Second commit message") ## Add more changes to repo 1 writeLines( c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", "minim veniam, quis nostrud exercitation ullamco laboris nisi ut"), con = file.path(path_repo_1, "test-1.txt")) add(repo_1, "test-1.txt") commit(repo_1, "Third commit message") ## Push to bare push(repo_1, "origin", paste0("refs/heads/", branch_name)) push(repo_1, "origin", "refs/heads/dev") ## Print branch branches(repo_1)[[paste0("origin/", branch_name)]] ## Clone to repo 2 repo_2 <- clone(url = path_bare, local_path = path_repo_2, branch = "dev") config(repo_2, user.name = "Bob", user.email = "bob@example.org") ## Check branch and commits stopifnot(identical(length(commits(repo_2)), 3L)) stopifnot(identical(repository_head(repo_2)$name, "dev")) ## Cleanup unlink(path_bare, recursive = TRUE) unlink(path_repo_1, recursive = TRUE) unlink(path_repo_2, recursive = TRUE) git2r/tests/fast_forward_merge.R0000644000176200001440000000432014530613147016431 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create directory for repository in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Create repository repo <- init(path, branch = "main") config(repo, user.name = "Alice", user.email = "alice@example.org") ## Add changes to repo writeLines("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", con = file.path(path, "test-1.txt")) add(repo, "test-1.txt") commit_1 <- commit(repo, "First commit message") ## Create branch and checkout checkout(branch_create(commit_1, name = "test")) ## Add changes to test branch writeLines(c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path, "test-1.txt")) add(repo, "test-1.txt") commit_2 <- commit(repo, "Second commit message") # Checkout main and merge b <- branches(repo) checkout(b[sapply(b, "[", "name") == "main"][[1]], force = TRUE) m <- merge(b[sapply(b, "[", "name") == "test"][[1]]) # Check merge stopifnot(inherits(m, "git_merge_result")) stopifnot(identical(m$up_to_date, FALSE)) stopifnot(identical(m$fast_forward, TRUE)) stopifnot(identical(m$conflicts, FALSE)) stopifnot(identical(sha(m), NA_character_)) stopifnot(identical(length(commits(repo)), 2L)) # Check reflog r <- reflog(repo) stopifnot(identical(r[[1]]$message, "merge test: Fast-forward")) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/checkout-named-branch.R0000644000176200001440000000574414530613147016726 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create directories for repositories in tempdir path_bare <- tempfile(pattern = "git2r-") path_repo_1 <- tempfile(pattern = "git2r-") path_repo_2 <- tempfile(pattern = "git2r-") dir.create(path_bare) dir.create(path_repo_1) dir.create(path_repo_2) ## Create bare repository bare_repo <- init(path_bare, bare = TRUE) ## Clone to repo 1 repo_1 <- clone(path_bare, path_repo_1) config(repo_1, user.name = "Alice", user.email = "alice@example.org") ## Add changes to repo 1 and push to bare writeLines( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", con = file.path(path_repo_1, "test.txt")) add(repo_1, "test.txt") commit(repo_1, "First commit message") branch_name <- branches(repo_1)[[1]]$name push(repo_1, "origin", paste0("refs/heads/", branch_name)) ## Test checkout branch argument tools::assertError(checkout(repo_1)) tools::assertError(checkout(repo_1, c("master", "master"))) tools::assertError(checkout(repo_1, "dev")) ## Create and checkout dev branch in repo 1 checkout(repo_1, "dev", create = TRUE) ## Add changes to dev branch in repo 1 and push to bare writeLines( c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path_repo_1, "test.txt")) add(repo_1, "test.txt") commit(repo_1, "Second commit message") push(repo_1, "origin", "refs/heads/dev") ## Clone to repo 2 repo_2 <- clone(path_bare, path_repo_2) config(repo_2, user.name = "Bob", user.email = "bob@example.org") stopifnot(identical( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", readLines(file.path(path_repo_2, "test.txt")))) ## Checkout dev branch checkout(repo_2, "dev") ## Check content of file stopifnot(identical( c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), readLines(file.path(path_repo_2, "test.txt")))) ## Checkout previous branch checkout(repo_2, "-") stopifnot(identical(repository_head(repo_2)$name, branch_name)) ## Cleanup unlink(path_bare, recursive = TRUE) unlink(path_repo_1, recursive = TRUE) unlink(path_repo_2, recursive = TRUE) git2r/tests/push.R0000644000176200001440000001107414530613147013554 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create 2 directories in tempdir path_bare <- tempfile(pattern = "git2r-") path_repo <- tempfile(pattern = "git2r-") dir.create(path_bare) dir.create(path_repo) ## Create repositories bare_repo <- init(path_bare, bare = TRUE) repo <- clone(path_bare, path_repo) ## Check the repositores stopifnot(identical(is_bare(bare_repo), TRUE)) stopifnot(identical(is_bare(repo), FALSE)) ## Config repositories config(repo, user.name = "Alice", user.email = "alice@example.org") ## Add changes to repo writeLines("Hello world", con = file.path(path_repo, "test.txt")) add(repo, "test.txt") commit_1 <- commit(repo, "Commit message") branch_name <- branches(repo)[[1]]$name ## Check commit stopifnot(identical(commit_1$author$name, "Alice")) stopifnot(identical(commit_1$author$email, "alice@example.org")) stopifnot(identical(length(commits(repo)), 1L)) stopifnot(identical(commits(repo)[[1]]$author$name, "Alice")) stopifnot(identical(commits(repo)[[1]]$author$email, "alice@example.org")) ## Check push arguments tools::assertError(push(repo, character(0), paste0("refs/heads/", branch_name))) tools::assertError(push(repo, NA_character_, paste0("refs/heads/", branch_name))) tools::assertError(push(repo, c("origin", "origin"), paste0("refs/heads/", branch_name))) tools::assertError(push(repo, "origin")) tools::assertError(push(repo, name = "origin")) push(repo, "origin", character(0)) push(repo, "origin", NA_character_) push(repo, "origin", c(NA_character_, NA_character_)) stopifnot(identical(reflog(repo, paste0("refs/remotes/origin/", branch_name)), structure(list(), class = "git_reflog"))) ## No tracking branch assigned to master tools::assertError(push(branches(repo)[[1]])) ## Push changes from repo to origin push(repo, "origin", paste0("refs/heads/", branch_name)) r <- reflog(repo, paste0("refs/remotes/origin/", branch_name)) stopifnot(identical(length(r), 1L)) r <- r[[1]] stopifnot(identical(sha(r), sha(commit_1))) stopifnot(identical(r$message, "update by push")) stopifnot(identical(r$index, 0L)) stopifnot(identical(r$committer$name, "Alice")) stopifnot(identical(r$committer$email, "alice@example.org")) stopifnot(identical(r$refname, paste0("refs/remotes/origin/", branch_name))) stopifnot(identical(r$repo$path, repo$path)) push(branches(repo)[[1]]) ## Check result in bare repository stopifnot(identical(length(commits(bare_repo)), 1L)) bare_commit_1 <- commits(bare_repo)[[1]] stopifnot(identical(sha(commit_1), sha(bare_commit_1))) stopifnot(identical(commit_1$author, bare_commit_1$author)) stopifnot(identical(commit_1$committer, bare_commit_1$committer)) stopifnot(identical(commit_1$summary, bare_commit_1$summary)) stopifnot(identical(commit_1$message, bare_commit_1$message)) stopifnot(!identical(commit_1$repo, bare_commit_1$repo)) ## Add changes to repo and push head writeLines(c("Hello world", "HELLO WORLD"), con = file.path(path_repo, "test.txt")) add(repo, "test.txt") commit_2 <- commit(repo, "Commit message 2") push(repo) bare_commit_2 <- lookup(bare_repo, sha(commit_2)) stopifnot(identical(sha(commit_2), sha(bare_commit_2))) stopifnot(identical(commit_2$author, bare_commit_2$author)) stopifnot(identical(commit_2$committer, bare_commit_2$committer)) stopifnot(identical(commit_2$summary, bare_commit_2$summary)) stopifnot(identical(commit_2$message, bare_commit_2$message)) stopifnot(!identical(commit_2$repo, bare_commit_2$repo)) ## Check 'set_upstream' branch_set_upstream(repository_head(repo), NULL) push(repo, "origin", paste0("refs/heads/", branch_name)) stopifnot(is.null(branch_get_upstream(repository_head(repo)))) push(repo, "origin", paste0("refs/heads/", branch_name), set_upstream = TRUE) stopifnot(!is.null(branch_get_upstream(repository_head(repo)))) ## Cleanup unlink(path_bare, recursive = TRUE) unlink(path_repo, recursive = TRUE) git2r/tests/clone_bare.R0000644000176200001440000000442614530613147014671 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create 2 directories in tempdir path_bare <- tempfile(pattern = "git2r-") path_repo <- tempfile(pattern = "git2r-") dir.create(path_bare) dir.create(path_repo) ## Initialize a repository repo <- init(path_repo) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Add commit to repo writeLines("Hello world", con = file.path(path_repo, "test.txt")) add(repo, "test.txt") commit_1 <- commit(repo, "Commit message") ## Check bare argument tools::assertError(clone(path_repo, path_bare, bare = c(TRUE, TRUE))) tools::assertError(clone(path_repo, path_bare, bare = 1)) tools::assertError(clone(path_repo, path_bare, bare = 1L)) tools::assertError(clone(path_repo, path_bare, bare = "test")) ## Clone repo to bare repository bare_repo <- clone(path_repo, path_bare, bare = TRUE) ## Check the repositores stopifnot(identical(is_bare(bare_repo), TRUE)) stopifnot(identical(is_bare(repo), FALSE)) ## Check result in bare repository stopifnot(identical(length(commits(bare_repo)), 1L)) bare_commit_1 <- commits(bare_repo)[[1]] stopifnot(identical(sha(commit_1), sha(bare_commit_1))) stopifnot(identical(commit_1$author, bare_commit_1$author)) stopifnot(identical(commit_1$committer, bare_commit_1$committer)) stopifnot(identical(commit_1$summary, bare_commit_1$summary)) stopifnot(identical(commit_1$message, bare_commit_1$message)) stopifnot(!identical(commit_1$repo, bare_commit_1$repo)) ## Cleanup unlink(path_bare, recursive = TRUE) unlink(path_repo, recursive = TRUE) git2r/tests/tree.R0000644000176200001440000000503714530613147013536 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file f <- file(file.path(path, "test.txt"), "wb") writeChar("Hello world!\n", f, eos = NULL) close(f) ## add and commit add(repo, "test.txt") commit(repo, "Commit message") ## Check tree stopifnot(is_tree(lookup(repo, "a0b0b9e615e9e433eb5f11859e9feac4564c58c5"))) stopifnot(identical( sha(lookup(repo, "a0b0b9e615e9e433eb5f11859e9feac4564c58c5")), "a0b0b9e615e9e433eb5f11859e9feac4564c58c5")) stopifnot(is_tree(tree(commits(repo)[[1]]))) stopifnot(identical(lookup(repo, "a0b0b9e615e9e433eb5f11859e9feac4564c58c5"), tree(commits(repo)[[1]]))) stopifnot(identical(length(tree(commits(repo)[[1]])), 1L)) ## Coerce to a data.frame and check column names stopifnot(identical(names(as.data.frame(tree(commits(repo)[[1]]))), c("mode", "type", "sha", "name"))) ## Coerce to list and check length stopifnot(identical(length(as.list(tree(last_commit(repo)))), 1L)) ## Print and summary stopifnot(identical(print(tree(last_commit(repo))), tree(last_commit(repo)))) summary(tree(last_commit(repo))) ## Check indexing stopifnot(is_blob(tree(last_commit(repo))[TRUE])) stopifnot(is_blob(tree(last_commit(repo))["test.txt"])) res <- tools::assertError(tree(last_commit(repo))[data.frame()]) stopifnot(length(grep("Invalid index", res[[1]]$message)) > 0) ## Check ls_tree stopifnot(identical(ls_tree(repo = repo), ls_tree(repo = path))) stopifnot(identical(ls_tree(tree = sha(tree(last_commit(repo))), repo = repo), ls_tree(repo = repo))) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/when.R0000644000176200001440000000547714530613147013550 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Check when method w1 <- structure(list(time = 1395567947, offset = 60), class = "git_time") stopifnot(identical(when(w1), "2014-03-23 09:45:47 GMT")) stopifnot(identical(when(w1, usetz = FALSE), "2014-03-23 09:45:47")) stopifnot(identical(when(w1, tz = "Europe/Stockholm", origin = "1980-02-02"), "2024-04-23 11:45:47 CEST")) s1 <- structure(list(name = "Alice", email = "alice@example.org", when = w1), class = "git_signature") stopifnot(identical(when(s1), "2014-03-23 09:45:47 GMT")) stopifnot(identical(when(s1, usetz = FALSE), "2014-03-23 09:45:47")) stopifnot(identical(when(s1, tz = "Europe/Stockholm", origin = "1980-02-02"), "2024-04-23 11:45:47 CEST")) w2 <- structure(list(time = 1395567950, offset = 60), class = "git_time") s2 <- structure(list(name = "Alice", email = "alice@example.org", when = w2), class = "git_signature") c1 <- structure(list(sha = "166f3f779fd7e4165aaa43f2828050ce040052b0", author = s1, committer = s2, summary = "A commit summary", message = "A commit message"), class = "git_commit") stopifnot(identical(when(c1), "2014-03-23 09:45:47 GMT")) stopifnot(identical(when(c1, usetz = FALSE), "2014-03-23 09:45:47")) stopifnot(identical(when(c1, tz = "Europe/Stockholm", origin = "1980-02-02"), "2024-04-23 11:45:47 CEST")) t1 <- structure(list(sha = "166f3f779fd7e4165aaa43f2828050ce040052b0", message = "A tag message", name = "A tage name", tagger = s1, target = "166f3f779fd7e4165aaa43f2828050ce040052b0"), class = "git_tag") stopifnot(identical(when(t1), "2014-03-23 09:45:47 GMT")) stopifnot(identical(when(t1, usetz = FALSE), "2014-03-23 09:45:47")) stopifnot(identical(when(t1, tz = "Europe/Stockholm", origin = "1980-02-02"), "2024-04-23 11:45:47 CEST")) git2r/tests/checkout_branch.R0000644000176200001440000000437314530613147015723 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path, branch = "main") config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create first commit writeLines("Hello world!", file.path(path, "test-1.txt")) add(repo, "test-1.txt") commit(repo, "First commit message") ## Create and checkout dev branch in repo checkout(repo, "dev", create = TRUE) ## Create second commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test-2.txt")) add(repo, "test-2.txt") commit(repo, "Second commit message") ## Check files stopifnot(identical(list.files(path), c("test-1.txt", "test-2.txt"))) ## Checkout master branch and check files checkout(repo, "main") stopifnot(identical(list.files(path), "test-1.txt")) ## Cleanup unlink(path, recursive = TRUE) ## Checkout branch in empty repository ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create and checkout dev branch in repo checkout(repo, "dev", create = TRUE) ## Create first commit writeLines("Hello world!", file.path(path, "test-1.txt")) add(repo, "test-1.txt") commit(repo, "First commit message") stopifnot(identical(length(branches(repo)), 1L)) stopifnot(identical(branches(repo)[[1]]$name, "dev")) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/bundle.R0000644000176200001440000000362514530613147014051 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(file.path(path, "bundle", "R"), recursive = TRUE) ## Initialize a repository repo <- init(file.path(path, "bundle")) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a DESCRIPTION file writeLines(c( "package: bundle", "Title: Bundle Git Repository", "Description: Bundle a bare repository of the code in the 'inst' folder.", "Version: 0.1", "License: GPL-2", "Authors@R: person('Alice', role = c('aut', 'cre'),", " email = 'alice@example.org')"), con = file.path(path, "bundle", "DESCRIPTION")) add(repo, file.path(path, "bundle", "DESCRIPTION")) commit(repo, "Add DESCRIPTION file") ## Create R file writeLines("f <- function(x, y) x+y", con = file.path(path, "bundle", "R", "bundle.R")) add(repo, file.path(path, "bundle", "R", "bundle.R")) commit(repo, "Add R file") ## Bundle package bundle_r_package(repo) ## Fails if bundled package exists tools::assertError(bundle_r_package(repo)) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/commits_path.R0000644000176200001440000002244414530613147015267 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path, branch = "main") config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create two files and alternate commits writeLines("1", file.path(path, "odd.txt")) add(repo, "odd.txt") c1 <- commit(repo, "commit 1") writeLines("2", file.path(path, "even.txt")) add(repo, "even.txt") c2 <- commit(repo, "commit 2") writeLines("3", file.path(path, "odd.txt")) add(repo, "odd.txt") c3 <- commit(repo, "commit 3") writeLines("4", file.path(path, "even.txt")) add(repo, "even.txt") c4 <- commit(repo, "commit 4") writeLines("5", file.path(path, "odd.txt")) add(repo, "odd.txt") c5 <- commit(repo, "commit 5") writeLines("6", file.path(path, "even.txt")) add(repo, "even.txt") c6 <- commit(repo, "commit 6") commits_all <- commits(repo) stopifnot(length(commits_all) == 6) ## Test path commits_odd <- commits(repo, path = "odd.txt") stopifnot(length(commits_odd) == 3) stopifnot(commits_odd[[1]]$sha == c5$sha) stopifnot(commits_odd[[2]]$sha == c3$sha) stopifnot(commits_odd[[3]]$sha == c1$sha) commits_even <- commits(repo, path = "even.txt") stopifnot(length(commits_even) == 3) stopifnot(commits_even[[1]]$sha == c6$sha) stopifnot(commits_even[[2]]$sha == c4$sha) stopifnot(commits_even[[3]]$sha == c2$sha) ## Test reverse commits_odd_rev <- commits(repo, reverse = TRUE, path = "odd.txt") stopifnot(length(commits_odd_rev) == 3) stopifnot(commits_odd_rev[[1]]$sha == c1$sha) stopifnot(commits_odd_rev[[2]]$sha == c3$sha) stopifnot(commits_odd_rev[[3]]$sha == c5$sha) commits_even_rev <- commits(repo, reverse = TRUE, path = "even.txt") stopifnot(length(commits_even_rev) == 3) stopifnot(commits_even_rev[[1]]$sha == c2$sha) stopifnot(commits_even_rev[[2]]$sha == c4$sha) stopifnot(commits_even_rev[[3]]$sha == c6$sha) ## Test n commits_odd_n <- commits(repo, n = 2, path = "odd.txt") stopifnot(length(commits_odd_n) == 2) stopifnot(commits_odd_n[[1]]$sha == c5$sha) stopifnot(commits_odd_n[[2]]$sha == c3$sha) commits_even_n <- commits(repo, n = 2, path = "even.txt") stopifnot(length(commits_even_n) == 2) stopifnot(commits_even_n[[1]]$sha == c6$sha) stopifnot(commits_even_n[[2]]$sha == c4$sha) commits_odd_0 <- commits(repo, n = 0, path = "odd.txt") stopifnot(length(commits_odd_0) == 0) stopifnot(identical(commits_odd_0, list())) commits_even_0 <- commits(repo, n = 0, path = "even.txt") stopifnot(length(commits_even_0) == 0) stopifnot(identical(commits_even_0, list())) ## Test ref checkout(repo, branch = "test-ref", create = TRUE) writeLines("7", file.path(path, "odd.txt")) add(repo, "odd.txt") c7 <- commit(repo, "commit 7") writeLines("8", file.path(path, "even.txt")) add(repo, "even.txt") c8 <- commit(repo, "commit 8") commits_odd_ref <- commits(repo, ref = "main", path = "odd.txt") stopifnot(length(commits_odd_ref) == 3) stopifnot(commits_odd_ref[[1]]$sha == c5$sha) stopifnot(commits_odd_ref[[2]]$sha == c3$sha) stopifnot(commits_odd_ref[[3]]$sha == c1$sha) commits_even_ref <- commits(repo, ref = "main", path = "even.txt") stopifnot(length(commits_even_ref) == 3) stopifnot(commits_even_ref[[1]]$sha == c6$sha) stopifnot(commits_even_ref[[2]]$sha == c4$sha) stopifnot(commits_even_ref[[3]]$sha == c2$sha) checkout(repo, branch = "main") ## Test renaming a file (path does not support --follow) writeLines("a file to be renamed", file.path(path, "original.txt")) add(repo, "original.txt") c_original <- commit(repo, "commit original") commits_original <- commits(repo, path = "original.txt") stopifnot(length(commits_original) == 1) stopifnot(commits_original[[1]]$sha == c_original$sha) file.rename(file.path(path, "original.txt"), file.path(path, "new.txt")) add(repo, c("original.txt", "new.txt")) c_new <- commit(repo, "commit new") commits_new <- commits(repo, path = "new.txt") stopifnot(length(commits_new) == 1) stopifnot(commits_new[[1]]$sha == c_new$sha) ## Test merge commits writeLines(letters[1:5], file.path(path, "merge.txt")) add(repo, "merge.txt") c_merge_1 <- commit(repo, "commit merge 1") checkout(repo, branch = "test-merge", create = TRUE) cat("z", file = file.path(path, "merge.txt"), append = TRUE) add(repo, "merge.txt") c_merge_2 <- commit(repo, "commit merge 2") checkout(repo, branch = "main") writeLines(c("A", letters[2:5]), file.path(path, "merge.txt")) add(repo, "merge.txt") c_merge_3 <- commit(repo, "commit merge 3") c_merge_4 <- merge(repo, "test-merge") stopifnot(class(c_merge_4) == "git_merge_result") commits_merge <- commits(repo, path = "merge.txt") stopifnot(length(commits_merge) == 4) stopifnot(commits_merge[[1]]$sha == c_merge_4$sha) stopifnot(commits_merge[[2]]$sha == c_merge_3$sha) stopifnot(commits_merge[[3]]$sha == c_merge_2$sha) stopifnot(commits_merge[[4]]$sha == c_merge_1$sha) ## Test absolute path writeLines("absolute", file.path(path, "abs.txt")) add(repo, "abs.txt") c_abs <- commit(repo, "commit absolute") commits_abs <- commits(repo, path = file.path(path, "abs.txt")) stopifnot(length(commits_abs) == 1) stopifnot(commits_abs[[1]]$sha == c_abs$sha) ## Test topological and time ## Strategy: ## - Commit a new file test-time.txt ## - Commit a change on branch test-time-1 (a) ## - Commit a change on branch test-time-2 (c) ## - Commit a change on branch test-time-1 (b) ## - Commit a change on branch test-time-2 (d) ## - Merge branch test-time-2 into main (fast-forward) ## - Merge branch test-time-1 into main (merge commit) ## ## $ git log --all --decorate --oneline --graph -n 6 ## * 79e6880 (HEAD -> main) merge test-time-1 ## |\ ## | * e2f18f1 (test-time-1) commit b ## | * 5f34820 commit a ## * | b954ec9 (test-time-2) commit d ## * | 7ae2fd5 commit c ## |/ ## * 923f3ea commit base Sys.sleep(1) writeLines(as.character(1:100), file.path(path, "test-time.txt")) add(repo, "test-time.txt") c_base <- commit(repo, "commit base") Sys.sleep(1) branch_create(commit = c_base, name = "test-time-1") branch_create(commit = c_base, name = "test-time-2") checkout(repo, branch = "test-time-1") writeLines(c("edit", 2:100), file.path(path, "test-time.txt")) add(repo, "test-time.txt") c_a <- commit(repo, "commit a") Sys.sleep(1) checkout(repo, branch = "test-time-2") writeLines(c(1:25, "edit", 27:100), file.path(path, "test-time.txt")) add(repo, "test-time.txt") c_c <- commit(repo, "commit c") Sys.sleep(1) checkout(repo, branch = "test-time-1") writeLines(c(1:50, "edit", 52:100), file.path(path, "test-time.txt")) add(repo, "test-time.txt") c_b <- commit(repo, "commit b") Sys.sleep(1) checkout(repo, branch = "test-time-2") writeLines(c(1:75, "edit", 77:100), file.path(path, "test-time.txt")) add(repo, "test-time.txt") c_d <- commit(repo, "commit d") Sys.sleep(1) checkout(repo, branch = "main") merge(repo, "test-time-2") # Fast-forward merge(repo, "test-time-1") # Merge commit c_merge_time <- commits(repo, n = 1)[[1]] ## topological - commits in test-time-2 come first because it was ## merged first stopifnot(identical( commits(repo, topological = TRUE, time = FALSE, path = "test-time.txt"), list(c_merge_time, c_b, c_a, c_d, c_c, c_base) )) stopifnot(identical( commits(repo, topological = TRUE, time = FALSE, path = "test-time.txt"), commits(repo, topological = TRUE, time = FALSE)[1:6] )) ## time - commits ordered by time they were created, not merged into ## main stopifnot(identical( commits(repo, topological = FALSE, time = TRUE, path = "test-time.txt"), list(c_merge_time, c_d, c_b, c_c, c_a, c_base) )) stopifnot(identical( commits(repo, topological = FALSE, time = TRUE, path = "test-time.txt"), commits(repo, topological = FALSE, time = TRUE)[1:6] )) ## topological and time - dominated by time stopifnot(identical( commits(repo, topological = TRUE, time = TRUE, path = "test-time.txt"), list(c_merge_time, c_d, c_b, c_c, c_a, c_base) )) stopifnot(identical( commits(repo, topological = TRUE, time = TRUE, path = "test-time.txt"), commits(repo, topological = TRUE, time = TRUE)[1:6] )) ## reverse with topological and/or time stopifnot(identical( commits(repo, topological = TRUE, time = FALSE, reverse = TRUE, path = "test-time.txt"), rev(list(c_merge_time, c_b, c_a, c_d, c_c, c_base)) )) stopifnot(identical( commits(repo, topological = FALSE, time = TRUE, reverse = TRUE, path = "test-time.txt"), rev(list(c_merge_time, c_d, c_b, c_c, c_a, c_base)) )) stopifnot(identical( commits(repo, topological = TRUE, time = TRUE, reverse = TRUE, path = "test-time.txt"), rev(list(c_merge_time, c_d, c_b, c_c, c_a, c_base)) )) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/reference.R0000644000176200001440000000331614530613147014533 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path, branch = "main") config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file writeLines("Hello world!", file.path(path, "test.txt")) ## add and commit add(repo, "test.txt") commit(repo, "Commit message") ## Check dwim of reference shorthand stopifnot(identical(.Call(git2r:::git2r_reference_dwim, repo, "")$name, "refs/heads/main")) stopifnot(identical(.Call(git2r:::git2r_reference_dwim, repo, "main")$name, "refs/heads/main")) stopifnot(identical( .Call(git2r:::git2r_reference_dwim, repo, "refs/heads/main")$name, "refs/heads/main")) ## print reference r <- .Call(git2r:::git2r_reference_dwim, repo, "refs/heads/main") stopifnot(identical(print(r), r)) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/status.R0000644000176200001440000001205714530613147014122 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) source("util/check.R") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Status case 1 status_exp_1 <- structure(list(staged = empty_named_list(), unstaged = empty_named_list(), untracked = empty_named_list()), class = "git_status") status_obs_1 <- status(repo) stopifnot(identical(print(status_obs_1), status_obs_1)) str(status_exp_1) str(status_obs_1) stopifnot(identical(status_obs_1, status_exp_1)) stopifnot(identical(capture.output(status(repo)), "working directory clean")) ## Status case 2, include ignored files status_exp_2 <- structure(list(staged = empty_named_list(), unstaged = empty_named_list(), untracked = empty_named_list(), ignored = empty_named_list()), class = "git_status") status_obs_2 <- status(repo, ignored = TRUE) status_obs_2 str(status_exp_2) str(status_obs_2) stopifnot(identical(status_obs_2, status_exp_2)) stopifnot(identical(capture.output(status(repo, ignored = TRUE)), "working directory clean")) ## Create 4 files writeLines("File-1", file.path(path, "test-1.txt")) writeLines("File-2", file.path(path, "test-2.txt")) writeLines("File-3", file.path(path, "test-3.txt")) writeLines("File-4", file.path(path, "test-4.txt")) ## Status case 3: 4 untracked files status_exp_3 <- structure(list(staged = empty_named_list(), unstaged = empty_named_list(), untracked = list(untracked = "test-1.txt", untracked = "test-2.txt", untracked = "test-3.txt", untracked = "test-4.txt")), class = "git_status") status_obs_3 <- status(repo) status_obs_3 str(status_exp_3) str(status_obs_3) stopifnot(identical(status_obs_3, status_exp_3)) ## Add file 1 and 2 to the repository and commit add(repo, c("test-1.txt", "test-2.txt")) commit(repo, "Commit message") ## Status case 4: 2 untracked files status_exp_4 <- structure(list(staged = empty_named_list(), unstaged = empty_named_list(), untracked = list(untracked = "test-3.txt", untracked = "test-4.txt")), class = "git_status") status_obs_4 <- status(repo) status_obs_4 str(status_exp_4) str(status_obs_4) stopifnot(identical(status_obs_4, status_exp_4)) ## Update file 1 & 2 writeLines(c("File-1", "Hello world"), file.path(path, "test-1.txt")) writeLines(c("File-2", "Hello world"), file.path(path, "test-2.txt")) ## Add file 1 add(repo, "test-1.txt") ## Status case 5: 1 staged file, 1 unstaged file and 2 untracked files status_exp_5 <- structure(list(staged = list(modified = "test-1.txt"), unstaged = list(modified = "test-2.txt"), untracked = list(untracked = "test-3.txt", untracked = "test-4.txt")), class = "git_status") status_obs_5 <- status(repo) status_obs_5 str(status_exp_5) str(status_obs_5) stopifnot(identical(status_obs_5, status_exp_5)) ## Add .gitignore file with file test-4.txt writeLines("test-4.txt", file.path(path, ".gitignore")) ## Status case 6: 1 staged file, 1 unstaged file, 2 untracked files ## and 1 ignored file status_exp_6 <- structure(list(staged = list(modified = "test-1.txt"), unstaged = list(modified = "test-2.txt"), untracked = list(untracked = ".gitignore", untracked = "test-3.txt"), ignored = list(ignored = "test-4.txt")), class = "git_status") status_obs_6 <- status(repo, ignore = TRUE) status_obs_6 str(status_exp_6) str(status_obs_6) stopifnot(identical(status_obs_6, status_exp_6)) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/config.R0000644000176200001440000001070514530613147014042 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) ## Config repository cfg <- config(repo, user.name = "Alice", user.email = "alice@example.org") ## Check configuration stopifnot(identical(print(cfg), cfg)) stopifnot("local" %in% names(cfg)) stopifnot("user.name" %in% names(cfg$local)) stopifnot(identical(cfg$local$user.name, "Alice")) stopifnot(identical(cfg$local$user.email, "alice@example.org")) ## Check that config fails for non-character entry. tools::assertError(config(repo, test = 5)) ## Check config method with missing repo argument wd <- setwd(path) cfg <- config(user.name = "Alice", user.email = "alice@example.org") stopifnot("local" %in% names(cfg)) stopifnot("user.name" %in% names(cfg$local)) stopifnot(identical(cfg$local$user.name, "Alice")) stopifnot(identical(cfg$local$user.email, "alice@example.org")) stopifnot(identical(git_config_files(repo = repo)$local, git_config_files(repo = NULL)$local)) stopifnot(identical(git_config_files(repo = repo)$local, git_config_files(repo = repo$path)$local)) if (!is.null(wd)) setwd(wd) ## Delete entries cfg <- config(repo, user.name = NULL, user.email = NULL) ## Check configuration stopifnot(is.null(cfg$local$user.name)) stopifnot(is.null(cfg$local$user.email)) ## Supply values as objects user_name <- "Alice" user_email <- "alice@example.org" cfg <- config(repo, user.name = user_name, user.email = "alice@example.org") stopifnot(identical(cfg$local$user.name, user_name)) stopifnot(identical(cfg$local$user.email, "alice@example.org")) cfg <- config(repo, user.name = "Alice", user.email = user_email) stopifnot(identical(cfg$local$user.name, "Alice")) stopifnot(identical(cfg$local$user.email, user_email)) ## Check git config files cfg <- git_config_files(repo) stopifnot(identical(nrow(cfg), 4L)) stopifnot(identical(names(cfg), c("file", "path"))) stopifnot(identical(cfg$file, c("system", "xdg", "global", "local"))) stopifnot(!is.na(cfg$path[4])) ## Check that the local config file is NA for an invalid repo ## argument. stopifnot(is.na(git_config_files(5)$local)) ## Check location of .gitconfig on Windows if (identical(Sys.getenv("APPVEYOR"), "True")) { ## AppVeyor diagnostics str(Sys.getenv("USERPROFILE")) str(Sys.getenv("HOMEDRIVE")) str(normalizePath("~")) str(git_config_files()) ## Temporarily move AppVeyor .gitconfig gitconfig_appveyor <- "C:/Users/appveyor/.gitconfig" gitconfig_tmp <- file.path(tempdir(), ".gitconfig") file.rename(gitconfig_appveyor, gitconfig_tmp) ## Test config() on Windows gitconfig_expected <- file.path(Sys.getenv("USERPROFILE"), ".gitconfig") ## .gitconfig should not be created if no configuration options specified config(global = TRUE) stopifnot(!file.exists(gitconfig_expected)) ## .gitconfig should be created in the user's home directory config(global = TRUE, user.name = "name", user.email = "email") stopifnot(file.exists(gitconfig_expected)) unlink(gitconfig_expected) ## .gitconfig should be created if user specifies option other than user.name ## and user.email config(global = TRUE, core.editor = "nano") stopifnot(file.exists(gitconfig_expected)) unlink(gitconfig_expected) ## .gitconfig should not create a new .gitconfig if the user already has one ## in Documents/ gitconfig_documents <- "~/.gitconfig" file.create(gitconfig_documents) config(global = TRUE, core.editor = "nano") stopifnot(!file.exists(gitconfig_expected)) unlink(gitconfig_documents) ## Return AppVeyor .gitconfig file.rename(gitconfig_tmp, gitconfig_appveyor) } ## Cleanup unlink(path, recursive = TRUE) git2r/tests/normal_merge.R0000644000176200001440000000533014530613147015242 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Initialize a temporary repository path <- tempfile(pattern = "git2r-") dir.create(path) repo <- init(path, branch = "main") ## Create a user and commit a file config(repo, user.name = "Author", user.email = "author@example.org") writeLines(c("First line in file 1.", "Second line in file 1."), file.path(path, "example-1.txt")) add(repo, "example-1.txt") commit(repo, "First commit message") ## Create and add one more file writeLines(c("First line in file 2.", "Second line in file 2."), file.path(path, "example-2.txt")) add(repo, "example-2.txt") commit(repo, "Second commit message") ## Create a new branch 'fix' checkout(repo, "fix", create = TRUE) ## Update 'example-1.txt' (swap words in first line) and commit writeLines(c("line First in file 1.", "Second line in file 1."), file.path(path, "example-1.txt")) add(repo, "example-1.txt") commit(repo, "Third commit message") checkout(repo, "main") ## Update 'example-2.txt' (swap words in second line) and commit writeLines(c("First line in file 2.", "line Second in file 2."), file.path(path, "example-2.txt")) add(repo, "example-2.txt") commit(repo, "Fourth commit message") # Missing branch to merge with should throw an error tools::assertError(merge(repo)) ## Merge 'fix' m <- merge(repo, "fix", TRUE, default_signature(repo)) stopifnot(identical(format(m), "Merge")) ## Merge 'fix' again m <- merge(repo, "fix", TRUE, default_signature(repo)) stopifnot(identical(format(m), "Already up-to-date")) ## Check number of parents of each commit stopifnot(identical(sapply(commits(repo), function(x) length(parents(x))), c(2L, 1L, 1L, 1L, 0L))) ## Check that last commit is a merge stopifnot(is_merge(last_commit(repo))) summary(last_commit(repo)) ## Check that metadata associated with merge is removed stopifnot(!file.exists(file.path(path, ".git", "MERGE_HEAD"))) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/commit.R0000644000176200001440000001733114530613147014067 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) source("util/check.R") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Commit without adding changes should produce an error tools::assertError(commit(repo, "Test to commit")) ## Create a file writeLines("Hello world!", file.path(path, "test.txt")) ## Commit without adding changes should produce an error tools::assertError(commit(repo, "Test to commit")) ## Add add(repo, "test.txt") ## Commit with empty message should produce an error tools::assertError(commit(repo, "")) ## Commit commit_1 <- commit(repo, "Commit message", session = TRUE) summary(commit_1) tag_1 <- tag(repo, "Tagname1", "Tag message 1") ## Check commit stopifnot(identical(commit_1$author$name, "Alice")) stopifnot(identical(commit_1$author$email, "alice@example.org")) stopifnot(identical(lookup(repo, sha(commit_1)), commit_1)) stopifnot(identical(length(commits(repo)), 1L)) stopifnot(identical(commits(repo)[[1]]$author$name, "Alice")) stopifnot(identical(commits(repo)[[1]]$author$email, "alice@example.org")) stopifnot(identical(parents(commit_1), list())) stopifnot(identical(print(commit_1), commit_1)) ## Check is_commit stopifnot(identical(is_commit(commit_1), TRUE)) stopifnot(identical(is_commit(5), FALSE)) ## Commit without adding changes should produce an error tools::assertError(commit(repo, "Test to commit")) ## Add another commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) add(repo, "test.txt") commit_2 <- commit(repo, "Commit message 2") summary(commit_2) tag_2 <- tag(repo, "Tagname2", "Tag message 2") ## Check relationship stopifnot(identical(descendant_of(commit_2, commit_1), TRUE)) stopifnot(identical(descendant_of(commit_1, commit_2), FALSE)) stopifnot(identical(descendant_of(tag_2, tag_1), TRUE)) stopifnot(identical(descendant_of(tag_1, tag_2), FALSE)) stopifnot(identical(descendant_of(branches(repo)[[1]], commit_1), TRUE)) stopifnot(identical(descendant_of(commit_1, branches(repo)[[1]]), FALSE)) stopifnot(identical(length(parents(commit_2)), 1L)) stopifnot(identical(parents(commit_2)[[1]], commit_1)) ## Check contributions stopifnot(identical( colnames(contributions(repo, by = "author", breaks = "day")), c("when", "author", "n"))) stopifnot(identical(colnames(contributions(repo)), c("when", "n"))) stopifnot(identical(nrow(contributions(repo)), 1L)) stopifnot(identical(contributions(repo)$n, 2L)) stopifnot(identical(contributions(repo, by = "author", breaks = "day")$n, 2L)) ## Add another commit with 'all' argument writeLines(c("Hello world!", "HELLO WORLD!", "HeLlO wOrLd!"), file.path(path, "test.txt")) commit(repo, "Commit message 3", all = TRUE) status_clean <- structure(list(staged = empty_named_list(), unstaged = empty_named_list(), untracked = empty_named_list()), class = "git_status") stopifnot(identical(status(repo), status_clean)) ## Delete file and commit with 'all' argument file.remove(file.path(path, "test.txt")) commit(repo, "Commit message 4", all = TRUE) stopifnot(identical(status(repo), status_clean)) ## Add and commit multiple tracked files with 'all' argument writeLines(sample(letters, 3), file.path(path, "test2.txt")) add(repo, "test2.txt") writeLines(sample(letters, 3), file.path(path, "test3.txt")) add(repo, "test3.txt") writeLines(sample(letters, 3), file.path(path, "test4.txt")) add(repo, "test4.txt") commit(repo, "Commit message 5") stopifnot(identical(status(repo), status_clean)) writeLines(sample(letters, 3), file.path(path, "test2.txt")) writeLines(sample(letters, 3), file.path(path, "test3.txt")) writeLines(sample(letters, 3), file.path(path, "test4.txt")) commit(repo, "Commit message 6", all = TRUE) stopifnot(identical(status(repo), status_clean)) ## Add one tracked file and delete another with 'all' argument writeLines(sample(letters, 3), file.path(path, "test2.txt")) file.remove(file.path(path, "test4.txt")) commit(repo, "Commit message 7", all = TRUE) stopifnot(identical(status(repo), status_clean)) ## Delete multiple tracked files with 'all' argument file.remove(file.path(path, "test2.txt")) file.remove(file.path(path, "test3.txt")) commit(repo, "Commit message 8", all = TRUE) stopifnot(identical(status(repo), status_clean)) ## Check max number of commits in output stopifnot(identical(length(commits(repo)), 8L)) stopifnot(identical(length(commits(repo, n = -1)), 8L)) stopifnot(identical(length(commits(repo, n = 2)), 2L)) tools::assertError(commits(repo, n = 2.2)) tools::assertError(commits(repo, n = "2")) tools::assertError(commits(repo, n = 1:2)) ## Check to coerce repository to data.frame df <- as.data.frame(repo) stopifnot(identical(dim(df), c(8L, 6L))) stopifnot(identical(names(df), c("sha", "summary", "message", "author", "email", "when"))) ## Set working directory to path and check commits setwd(path) stopifnot(identical(sha(last_commit()), sha(commits(repo, n = 1)[[1]]))) stopifnot(identical(length(commits()), 8L)) stopifnot(identical(length(commits(n = -1)), 8L)) stopifnot(identical(length(commits(n = 2)), 2L)) tools::assertError(commits(n = 2.2)) tools::assertError(commits(n = "2")) ## Check plot method plot_file <- tempfile(fileext = ".pdf") pdf(plot_file) plot(repo) dev.off() stopifnot(file.exists(plot_file)) unlink(plot_file) ## Check punch card plot method punch_card_plot_file <- tempfile(fileext = ".pdf") pdf(punch_card_plot_file) punch_card(repo) dev.off() stopifnot(file.exists(punch_card_plot_file)) unlink(punch_card_plot_file) ## Check that 'git2r_arg_check_commit' raise error res <- tools::assertError(.Call(git2r:::git2r_commit_tree, NULL)) stopifnot(length(grep("'commit' must be an S3 class git_commit", res[[1]]$message)) > 0) res <- tools::assertError(.Call(git2r:::git2r_commit_tree, 3)) stopifnot(length(grep("'commit' must be an S3 class git_commit", res[[1]]$message)) > 0) res <- tools::assertError(.Call(git2r:::git2r_commit_tree, repo)) stopifnot(length(grep("'commit' must be an S3 class git_commit", res[[1]]$message)) > 0) commit_1$sha <- NA_character_ res <- tools::assertError(.Call(git2r:::git2r_commit_tree, commit_1)) stopifnot(length(grep("'commit' must be an S3 class git_commit", res[[1]]$message)) > 0) ## Cleanup unlink(path, recursive = TRUE) if (identical(Sys.getenv("NOT_CRAN"), "true") || identical(Sys.getenv("R_COVR"), "true")) { path <- tempfile(pattern = "git2r-") dir.create(path) setwd(path) system("git clone --depth 2 https://github.com/ropensci/git2r.git") ## Check the number of commits in the shallow clone. stopifnot(identical(length(commits(repository("git2r"))), 2L)) stopifnot(identical(length(commits(repository("git2r"), n = 1)), 1L)) ## Cleanup unlink(path, recursive = TRUE) } git2r/tests/remotes.R0000644000176200001440000000470214530613147014253 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file writeLines("Hello world!", file.path(path, "test.txt")) ## Add and commit add(repo, "test.txt") commit_1 <- commit(repo, "Commit message") ## Add a remote remote_add(repo, "playground", "https://github.com/gaborcsardi/playground") stopifnot(identical(remotes(repo), "playground")) stopifnot(identical(remote_url(repo, "playground"), "https://github.com/gaborcsardi/playground")) stopifnot(identical(remote_url(repo), "https://github.com/gaborcsardi/playground")) ## Rename a remote remote_rename(repo, "playground", "foobar") stopifnot(identical(remotes(repo), "foobar")) stopifnot(identical(remote_url(repo, "foobar"), "https://github.com/gaborcsardi/playground")) ## Set remote url remote_set_url(repo, "foobar", "https://github.com/stewid/playground") stopifnot(identical(remote_url(repo, "foobar"), "https://github.com/stewid/playground")) ## Remove a remote remote_remove(repo, "foobar") stopifnot(identical(remotes(repo), character(0))) if (identical(Sys.getenv("NOT_CRAN"), "true")) { if (isTRUE(libgit2_features()$https)) { refs <- remote_ls("https://github.com/ropensci/git2r") stopifnot(length(refs) > 0) stopifnot(names(refs) > 0) stopifnot(any(names(refs) == "HEAD")) } } # an invalid URL should throw an error tools::assertError(remote_ls("bad")) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/blame.R0000644000176200001440000000567314530613147013665 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file and commit writeLines("Hello world!", file.path(path, "test.txt")) add(repo, "test.txt") commit_1 <- commit(repo, "First commit message") ## Create new user and change file config(repo, user.name = "Bob", user.email = "bob@example.org") writeLines(c("Hello world!", "HELLO WORLD!", "HOLA"), file.path(path, "test.txt")) add(repo, "test.txt") commit_2 <- commit(repo, "Second commit message") ## Check blame b <- blame(repo, "test.txt") stopifnot(identical(length(b$hunks), 2L)) ## Hunk: 1 stopifnot(identical(b$hunks[[1]]$lines_in_hunk, 1L)) stopifnot(identical(b$hunks[[1]]$final_commit_id, sha(commit_1))) stopifnot(identical(b$hunks[[1]]$final_start_line_number, 1L)) stopifnot(identical(b$hunks[[1]]$final_signature$name, "Alice")) stopifnot(identical(b$hunks[[1]]$final_signature$email, "alice@example.org")) stopifnot(identical(b$hunks[[1]]$orig_commit_id, sha(commit_1))) stopifnot(identical(b$hunks[[1]]$orig_start_line_number, 1L)) stopifnot(identical(b$hunks[[1]]$orig_signature$name, "Alice")) stopifnot(identical(b$hunks[[1]]$orig_signature$email, "alice@example.org")) stopifnot(identical(b$hunks[[1]]$orig_path, "test.txt")) stopifnot(identical(b$hunks[[1]]$boundary, TRUE)) ## Hunk: 2 stopifnot(identical(b$hunks[[2]]$lines_in_hunk, 2L)) stopifnot(identical(b$hunks[[2]]$final_commit_id, sha(commit_2))) stopifnot(identical(b$hunks[[2]]$final_start_line_number, 2L)) stopifnot(identical(b$hunks[[2]]$final_signature$name, "Bob")) stopifnot(identical(b$hunks[[2]]$final_signature$email, "bob@example.org")) stopifnot(identical(b$hunks[[2]]$orig_commit_id, sha(commit_2))) stopifnot(identical(b$hunks[[2]]$orig_start_line_number, 2L)) stopifnot(identical(b$hunks[[2]]$orig_signature$name, "Bob")) stopifnot(identical(b$hunks[[2]]$orig_signature$email, "bob@example.org")) stopifnot(identical(b$hunks[[2]]$orig_path, "test.txt")) stopifnot(identical(b$hunks[[2]]$boundary, FALSE)) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/time.R0000644000176200001440000000457014530613147013536 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Test to coerce git_t <- structure(list(time = 1395567947, offset = 60), class = "git_time") stopifnot(identical(as.character(git_t), "2014-03-23 09:45:47 GMT")) stopifnot(identical(as.character(git_t, usetz = FALSE), "2014-03-23 09:45:47")) stopifnot(identical(as.POSIXct(git_t), as.POSIXct(1395567947, tz = "GMT", origin = "1970-01-01"))) stopifnot(identical(print(git_t), git_t)) as.POSIXct(1395567947, origin = "1970-01-01", tz = "-03") ## Test that origin/tz can be passed to as.POSIXct stopifnot(identical(as.POSIXct(git_t, tz = "Europe/Stockholm", origin = "1980-02-02"), as.POSIXct(1395567947, tz = "Europe/Stockholm", origin = "1980-02-02"))) ## Test that origin/tz can be passed to as.character stopifnot(identical(as.character(git_t, tz = "Europe/Stockholm", origin = "1980-02-02"), "2024-04-23 11:45:47 CEST")) stopifnot(identical(as.character(git_t, tz = "Europe/Stockholm", origin = "1980-02-02", usetz = FALSE), "2024-04-23 11:45:47")) ## Test that origin/tz can be passed to print stopifnot(identical( utils::capture.output(print(git_t, tz = "Europe/Stockholm", origin = "1980-02-02")), "2024-04-23 11:45:47 CEST" )) stopifnot(identical( utils::capture.output(print(git_t, tz = "Europe/Stockholm", origin = "1980-02-02", usetz = FALSE)), "2024-04-23 11:45:47" )) git2r/tests/fetch.R0000644000176200001440000001463014530613147013667 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create 2 directories in tempdir path_bare <- tempfile(pattern = "git2r-") path_repo_1 <- tempfile(pattern = "git2r-") path_repo_2 <- tempfile(pattern = "git2r-") dir.create(path_bare) dir.create(path_repo_1) dir.create(path_repo_2) ## Create repositories bare_repo <- init(path_bare, bare = TRUE) repo_1 <- clone(path_bare, path_repo_1) repo_2 <- clone(path_bare, path_repo_2) ## Config repositories config(repo_1, user.name = "Alice", user.email = "alice@example.org") config(repo_2, user.name = "Bob", user.email = "bob@example.org") ## Add changes to repo 1 writeLines("Hello world", con = file.path(path_repo_1, "test.txt")) add(repo_1, "test.txt") commit_1 <- commit(repo_1, "Commit message") branch_name <- branches(repo_1)[[1]]$name ## Push changes from repo 1 to origin push(repo_1, "origin", paste0("refs/heads/", branch_name)) ## Check result in bare repository stopifnot(identical(length(commits(bare_repo)), 1L)) bare_commit_1 <- commits(bare_repo)[[1]] stopifnot(identical(sha(commit_1), sha(bare_commit_1))) stopifnot(identical(commit_1$author, bare_commit_1$author)) stopifnot(identical(commit_1$committer, bare_commit_1$committer)) stopifnot(identical(commit_1$summary, bare_commit_1$summary)) stopifnot(identical(commit_1$message, bare_commit_1$message)) stopifnot(!identical(commit_1$repo, bare_commit_1$repo)) ## Fetch fetch(repo_2, "origin") fh <- fetch_heads(repo_2)[[1]] stopifnot(identical(sha(fh), fh$sha)) ## Test show method of non-empty repository where head is null show(repo_2) ## Check that 'git2r_arg_check_credentials' raise error res <- tools::assertError( .Call(git2r:::git2r_remote_fetch, repo_1, "origin", 3, "fetch", FALSE, NULL)) stopifnot(length(grep("'credentials' must be an S3 class with credentials", res[[1]]$message)) > 0) res <- tools::assertError( .Call(git2r:::git2r_remote_fetch, repo_1, "origin", repo_1, "fetch", FALSE, NULL)) stopifnot(length(grep("'credentials' must be an S3 class with credentials", res[[1]]$message)) > 0) credentials <- cred_env(c("username", "username"), "password") res <- tools::assertError( .Call(git2r:::git2r_remote_fetch, repo_1, "origin", credentials, "fetch", FALSE, NULL)) stopifnot(length(grep("'credentials' must be an S3 class with credentials", res[[1]]$message)) > 0) credentials <- cred_env("username", c("password", "passowrd")) res <- tools::assertError( .Call(git2r:::git2r_remote_fetch, repo_1, "origin", credentials, "fetch", FALSE, NULL)) stopifnot(length(grep("'credentials' must be an S3 class with credentials", res[[1]]$message)) > 0) credentials <- cred_user_pass(c("username", "username"), "password") res <- tools::assertError( .Call(git2r:::git2r_remote_fetch, repo_1, "origin", credentials, "fetch", FALSE, NULL)) stopifnot(length(grep("'credentials' must be an S3 class with credentials", res[[1]]$message)) > 0) credentials <- cred_user_pass("username", c("password", "passowrd")) res <- tools::assertError( .Call(git2r:::git2r_remote_fetch, repo_1, "origin", credentials, "fetch", FALSE, NULL)) stopifnot(length(grep("'credentials' must be an S3 class with credentials", res[[1]]$message)) > 0) credentials <- cred_token(c("GITHUB_PAT", "GITHUB_PAT")) res <- tools::assertError( .Call(git2r:::git2r_remote_fetch, repo_1, "origin", credentials, "fetch", FALSE, NULL)) stopifnot(length(grep("'credentials' must be an S3 class with credentials", res[[1]]$message)) > 0) credentials <- structure(list(publickey = c("id_rsa.pub", "id_rsa.pub"), privatekey = "id_rsa", passphrase = character(0)), class = "cred_ssh_key") res <- tools::assertError( .Call(git2r:::git2r_remote_fetch, repo_1, "origin", credentials, "fetch", FALSE, NULL)) stopifnot(length(grep("'credentials' must be an S3 class with credentials", res[[1]]$message)) > 0) credentials <- structure(list(publickey = "id_rsa.pub", privatekey = c("id_rsa", "id_rsa"), passphrase = character(0)), class = "cred_ssh_key") res <- tools::assertError( .Call(git2r:::git2r_remote_fetch, repo_1, "origin", credentials, "fetch", FALSE, NULL)) stopifnot(length(grep("'credentials' must be an S3 class with credentials", res[[1]]$message)) > 0) credentials <- structure(list(publickey = "id_rsa.pub", privatekey = "id_rsa", passphrase = NA_character_), class = "cred_ssh_key") res <- tools::assertError( .Call(git2r:::git2r_remote_fetch, repo_1, "origin", credentials, "fetch", FALSE, NULL)) stopifnot(length(grep("'credentials' must be an S3 class with credentials", res[[1]]$message)) > 0) credentials <- structure(list(publickey = "id_rsa.pub", privatekey = "id_rsa", passphrase = c("passphrase", "passphrase")), class = "cred_ssh_key") res <- tools::assertError( .Call(git2r:::git2r_remote_fetch, repo_1, "origin", credentials, "fetch", FALSE, NULL)) stopifnot(length(grep("'credentials' must be an S3 class with credentials", res[[1]]$message)) > 0) ## Cleanup unlink(path_bare, recursive = TRUE) unlink(path_repo_1, recursive = TRUE) unlink(path_repo_2, recursive = TRUE) git2r/tests/reset.R0000644000176200001440000001032214530613147013712 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) source("util/check.R") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file writeLines("Hello world!", file.path(path, "test-1.txt")) ## Add and reset an empty repository using a path add(repo, "test-1.txt") stopifnot(identical( status(repo), structure(list(staged = list(new = "test-1.txt"), unstaged = empty_named_list(), untracked = empty_named_list()), class = "git_status"))) reset(repo, path = "test-1.txt") stopifnot(identical( status(repo), structure(list(staged = empty_named_list(), unstaged = empty_named_list(), untracked = list(untracked = "test-1.txt")), class = "git_status"))) ## Add and reset a non-empty repository using a path add(repo, "test-1.txt") commit(repo, "First commit") writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test-1.txt")) add(repo, "test-1.txt") stopifnot(identical( status(repo), structure(list(staged = list(modified = "test-1.txt"), unstaged = empty_named_list(), untracked = empty_named_list()), class = "git_status"))) reset(repo, path = "test-1.txt") stopifnot(identical( status(repo), structure(list(staged = empty_named_list(), unstaged = list(modified = "test-1.txt"), untracked = empty_named_list()), class = "git_status"))) ## add and commit add(repo, "test-1.txt") commit_1 <- commit(repo, "Commit message") ## Make one more commit writeLines(c("Hello world!", "HELLO WORLD!", "hello world!"), file.path(path, "test-1.txt")) add(repo, "test-1.txt") commit(repo, "Next commit message") ## Create one more file writeLines("Hello world!", file.path(path, "test-2.txt")) ## 'soft' reset to first commit reset(commit_1) soft_exp <- structure(list(staged = list(modified = "test-1.txt"), unstaged = empty_named_list(), untracked = list(untracked = "test-2.txt")), class = "git_status") soft_obs <- status(repo) stopifnot(identical(soft_obs, soft_exp)) stopifnot(identical(length(commits(repo)), 2L)) stopifnot(identical(commits(repo)[[1]], commit_1)) ## 'mixed' reset to first commit commit(repo, "Next commit message") reset(commit_1, "mixed") mixed_exp <- structure(list(staged = empty_named_list(), unstaged = list(modified = "test-1.txt"), untracked = list(untracked = "test-2.txt")), class = "git_status") mixed_obs <- status(repo) stopifnot(identical(mixed_obs, mixed_exp)) stopifnot(identical(length(commits(repo)), 2L)) stopifnot(identical(commits(repo)[[1]], commit_1)) ## 'hard' reset to first commit add(repo, "test-1.txt") commit(repo, "Next commit message") reset(commit_1, "hard") hard_exp <- structure(list(staged = empty_named_list(), unstaged = empty_named_list(), untracked = list(untracked = "test-2.txt")), class = "git_status") hard_obs <- status(repo) stopifnot(identical(hard_obs, hard_exp)) stopifnot(identical(length(commits(repo)), 2L)) stopifnot(identical(commits(repo)[[1]], commit_1)) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/note.R0000644000176200001440000000645414530613147013550 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit writeLines("Hello world!", file.path(path, "test.txt")) add(repo, "test.txt") commit_1 <- commit(repo, "Commit message 1") ## Create another commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) add(repo, "test.txt") commit_2 <- commit(repo, "Commit message 2") ## Check default ref stopifnot(identical(note_default_ref(repo), "refs/notes/commits")) ## Check that an invalid object argument in note_create produce an ## error. tools::assertError(note_create(object = NULL, message = "test")) tools::assertError(note_create(object = 1, message = "test")) ## Check that notes is an empty list stopifnot(identical(notes(repo), list())) ## Create note in default namespace note_1 <- note_create(commit_1, "Note-1") stopifnot(identical(print(note_1), note_1)) stopifnot(identical(length(notes(repo)), 1L)) stopifnot(identical(sha(note_1), note_1$sha)) tools::assertError(note_create(commit_1, "Note-2")) note_2 <- note_create(commit_1, "Note-2", force = TRUE) stopifnot(identical(length(notes(repo)), 1L)) ## Check that an invalid note argument in note_remove produce an ## error. tools::assertError(note_remove(note = 1)) ## Create note in named (review) namespace note_3 <- note_create(commit_1, "Note-3", ref = "refs/notes/review") note_4 <- note_create(commit_2, "Note-4", ref = "refs/notes/review") stopifnot(identical(length(notes(repo, ref = "refs/notes/review")), 2L)) note_remove(note_3) note_remove(note_4) stopifnot(identical(notes(repo, ref = "refs/notes/review"), list())) note_5 <- note_create(commit_1, "Note-5", ref = "review") note_6 <- note_create(commit_2, "Note-6", ref = "review") stopifnot(identical(length(notes(repo, ref = "review")), 2L)) note_remove(note_5) note_remove(note_6) stopifnot(identical(length(notes(repo, ref = "review")), 0L)) ## Create note on blob and tree tree_1 <- tree(commit_1) note_7 <- note_create(tree_1, "Note-7") stopifnot(is(object = lookup(repo, note_7$annotated), class2 = "git_tree")) stopifnot(identical(length(notes(repo)), 2L)) blob_1 <- lookup(repo, tree_1$id[1]) note_8 <- note_create(blob_1, "Note-8") stopifnot(is(object = lookup(repo, note_8$annotated), class2 = "git_blob")) stopifnot(identical(length(notes(repo)), 3L)) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/blob.R0000644000176200001440000001361514530613147013516 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) library(tools) source("util/check.R") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file f <- file(file.path(path, "test.txt"), "wb") writeChar("Hello world!\n", f, eos = NULL) close(f) ## add and commit add(repo, "test.txt") new_commit <- commit(repo, "Commit message") ## Lookup blob blob <- lookup(repo, "cd0875583aabe89ee197ea133980a9085d08e497") stopifnot(isTRUE(is_blob(blob))) stopifnot(identical(sha(blob), "cd0875583aabe89ee197ea133980a9085d08e497")) stopifnot(identical(is_binary(blob), FALSE)) stopifnot(identical(blob, lookup(repo, "cd0875"))) stopifnot(identical(length(blob), 13L)) stopifnot(identical(content(blob), "Hello world!")) stopifnot(identical(print(blob), blob)) ## Add one more commit f <- file(file.path(path, "test.txt"), "wb") writeChar("Hello world!\nHELLO WORLD!\nHeLlO wOrLd!\n", f, eos = NULL) close(f) add(repo, "test.txt") blob <- lookup(repo, tree(commit(repo, "New commit message"))$id[1]) stopifnot(identical(content(blob), c("Hello world!", "HELLO WORLD!", "HeLlO wOrLd!"))) stopifnot(identical(rawToChar(content(blob, raw = TRUE)), content(blob, split = FALSE))) ## Check content of binary file set.seed(42) x <- as.raw((sample(0:255, 1000, replace = TRUE))) writeBin(x, con = file.path(path, "test.bin")) add(repo, "test.bin") commit(repo, "Add binary file") blob <- tree(last_commit(repo))["test.bin"] stopifnot(identical(content(blob), NA_character_)) stopifnot(identical(x, content(blob, raw = TRUE))) ## Hash stopifnot(identical(hash("Hello, world!\n"), "af5626b4a114abcb82d63db7c8082c3c4756e51b")) stopifnot(identical(hash("test content\n"), "d670460b4b4aece5915caf5c68d12f560a9fe3e4")) stopifnot(identical(hash(c("Hello, world!\n", "test content\n")), c("af5626b4a114abcb82d63db7c8082c3c4756e51b", "d670460b4b4aece5915caf5c68d12f560a9fe3e4"))) stopifnot(identical(hash(c("Hello, world!\n", NA_character_, "test content\n")), c("af5626b4a114abcb82d63db7c8082c3c4756e51b", NA_character_, "d670460b4b4aece5915caf5c68d12f560a9fe3e4"))) stopifnot(identical(hash(character(0)), character(0))) ## Hash file test_1_txt <- file(file.path(path, "test-1.txt"), "wb") writeChar("Hello, world!\n", test_1_txt, eos = NULL) close(test_1_txt) test_2_txt <- file(file.path(path, "test-2.txt"), "wb") writeChar("test content\n", test_2_txt, eos = NULL) close(test_2_txt) stopifnot(identical(hash("Hello, world!\n"), hashfile(file.path(path, "test-1.txt")))) stopifnot(identical(hash("test content\n"), hashfile(file.path(path, "test-2.txt")))) stopifnot(identical(hash(c("Hello, world!\n", "test content\n")), hashfile(c(file.path(path, "test-1.txt"), file.path(path, "test-2.txt"))))) assertError(hashfile(c(file.path(path, "test-1.txt"), NA_character_, file.path(path, "test-2.txt")))) stopifnot(identical(hashfile(character(0)), character(0))) ## Create blob from disk tmp_file_1 <- tempfile() tmp_file_2 <- tempfile() f1 <- file(tmp_file_1, "wb") writeChar("Hello, world!\n", f1, eos = NULL) close(f1) f2 <- file(tmp_file_2, "wb") writeChar("test content\n", f2, eos = NULL) close(f2) blob_list_1 <- blob_create(repo, c(tmp_file_1, tmp_file_2), relative = FALSE) unlink(tmp_file_1) unlink(tmp_file_2) stopifnot(identical(sapply(blob_list_1, "[[", "sha"), c("af5626b4a114abcb82d63db7c8082c3c4756e51b", "d670460b4b4aece5915caf5c68d12f560a9fe3e4"))) ## Create blob from workdir tmp_file_3 <- file.path(path, "test-workdir-1.txt") tmp_file_4 <- file.path(path, "test-workdir-2.txt") f3 <- file(tmp_file_3, "wb") writeChar("Hello, world!\n", f3, eos = NULL) close(f3) f4 <- file(tmp_file_4, "wb") writeChar("test content\n", f4, eos = NULL) close(f4) blob_list_2 <- blob_create(repo, c("test-workdir-1.txt", "test-workdir-2.txt")) stopifnot(identical(sapply(blob_list_2, "[[", "sha"), c("af5626b4a114abcb82d63db7c8082c3c4756e51b", "d670460b4b4aece5915caf5c68d12f560a9fe3e4"))) ## Test arguments check_error(assertError(.Call(git2r:::git2r_blob_content, NULL, FALSE)), "'blob' must be an S3 class git_blob") check_error(assertError(.Call(git2r:::git2r_blob_content, 3, FALSE)), "'blob' must be an S3 class git_blob") check_error(assertError(.Call(git2r:::git2r_blob_content, repo, FALSE)), "'blob' must be an S3 class git_blob") b <- blob_list_1[[1]] b$sha <- NA_character_ check_error(assertError(.Call(git2r:::git2r_blob_content, b, FALSE)), "'blob' must be an S3 class git_blob") check_error(assertError(hashfile(NA)), "invalid 'path' argument") ## Cleanup unlink(path, recursive = TRUE) git2r/tests/ls_tree.R0000644000176200001440000000472314530613147014235 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Initialize a temporary repository path <- tempfile(pattern = "git2r-") dir.create(path) dir.create(file.path(path, "subfolder")) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create three files and commit writeLines("First file", file.path(path, "example-1.txt")) writeLines("Second file", file.path(path, "subfolder/example-2.txt")) writeLines("Third file", file.path(path, "example-3.txt")) add(repo, c("example-1.txt", "subfolder/example-2.txt", "example-3.txt")) commit(repo, "Commit message") ## Traverse tree entries and its subtrees. ## Various approaches that give identical result. stopifnot(identical(ls_tree(tree = tree(last_commit(path))), ls_tree(tree = tree(last_commit(repo))))) stopifnot(identical(ls_tree(repo = path), ls_tree(repo = repo))) ## ls_tree(repo = repo) should match `git ls-tree -lr HEAD` ls_tree_result <- ls_tree(repo = repo) stopifnot(identical(ls_tree_result$name, c("example-1.txt", "example-3.txt", "example-2.txt"))) # Argument `tree` can be a 'character that identifies a tree in the repository' ls_tree(tree = tree(last_commit(path))$sha, repo = repo) ## Skip content in subfolder ls_tree_toplevel <- ls_tree(repo = repo, recursive = FALSE) stopifnot(nrow(ls_tree_toplevel) == 3) stopifnot(identical(ls_tree_toplevel$name, c("example-1.txt", "example-3.txt", "subfolder"))) ## Start in subfolder ls_tree_subfolder <- ls_tree(tree = "HEAD:subfolder", repo = repo) stopifnot(nrow(ls_tree_subfolder) == 1) stopifnot(identical(ls_tree_subfolder$name, "example-2.txt")) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/diff.R0000644000176200001440000001506114530613147013505 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add, commit writeLines("Hello world!", file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Commit message") ## Change the file, diff between index and workdir writeLines("Hello again!\nHere is a second line\nAnd a third", file.path(path, "test.txt")) diff_1 <- diff(repo) diff(repo, as_char = TRUE) diff(repo, as_char = TRUE, filename = file.path(path, "test.diff")) stopifnot(identical(diff_1$old, "index")) stopifnot(identical(diff_1$new, "workdir")) stopifnot(identical(length(diff_1$files), 1L)) stopifnot(identical(diff_1$files[[1]]$old_file, "test.txt")) stopifnot(identical(diff_1$files[[1]]$new_file, "test.txt")) stopifnot(identical(length(diff_1$files[[1]]$hunks), 1L)) stopifnot(identical(length(diff_1$files[[1]]$hunks[[1]]$lines), 4L)) ## TODO: check actual diff ## Diff between index and HEAD is empty diff_2 <- diff(repo, index = TRUE) diff(repo, as_char = TRUE) diff(repo, as_char = TRUE, filename = file.path(path, "test.diff")) stopifnot(identical(diff_2$old, "HEAD")) stopifnot(identical(diff_2$new, "index")) stopifnot(identical(diff_2$files, list())) ## Diff between tree and working dir, same as diff_1 diff_3 <- diff(tree(commits(repo)[[1]])) diff(repo, as_char = TRUE) diff(repo, as_char = TRUE, filename = file.path(path, "test.diff")) stopifnot(identical(diff_3$old, tree(commits(repo)[[1]]))) stopifnot(identical(diff_3$new, "workdir")) stopifnot(identical(diff_3$files, diff_1$files)) stopifnot(identical(print(diff_3), diff_3)) ## Add changes, diff between index and HEAD is the same as diff_1 add(repo, "test.txt") diff_4 <- diff(repo, index = TRUE) diff(repo, as_char = TRUE) diff(repo, as_char = TRUE, filename = file.path(path, "test.diff")) stopifnot(identical(diff_4$old, "HEAD")) stopifnot(identical(diff_4$new, "index")) stopifnot(identical(diff_4$files, diff_1$files)) ## Diff between tree and index diff_5 <- diff(tree(commits(repo)[[1]]), index = TRUE) diff(repo, as_char = TRUE) diff(repo, as_char = TRUE, filename = file.path(path, "test.diff")) stopifnot(identical(diff_5$old, tree(commits(repo)[[1]]))) stopifnot(identical(diff_5$new, "index")) stopifnot(identical(diff_5$files, diff_1$files)) ## Diff between two trees commit(repo, "Second commit") tree_1 <- tree(commits(repo)[[2]]) tree_2 <- tree(commits(repo)[[1]]) diff_6 <- diff(tree_1, tree_2) diff(repo, as_char = TRUE) diff(repo, as_char = TRUE, filename = file.path(path, "test.diff")) stopifnot(identical(diff_6$old, tree_1)) stopifnot(identical(diff_6$new, tree_2)) stopifnot(identical(diff_6$files, diff_1$files)) ## Length of a diff stopifnot(identical(length(diff_1), 1L)) stopifnot(identical(length(diff_2), 0L)) stopifnot(identical(length(diff_3), 1L)) stopifnot(identical(length(diff_4), 1L)) stopifnot(identical(length(diff_5), 1L)) stopifnot(identical(length(diff_6), 1L)) ## Binary files set.seed(42) writeBin(as.raw((sample(0:255, 1000, replace = TRUE))), con = file.path(path, "test.bin")) add(repo, "test.bin") diff_7 <- diff(repo, index = TRUE) diff(repo, as_char = TRUE) diff(repo, as_char = TRUE, filename = file.path(path, "test.diff")) stopifnot(any(grepl("binary file", capture.output(summary(diff_7))))) ## TODO: errors ## Check non-logical index argument res <- tools::assertError( .Call(git2r:::git2r_diff, NULL, NULL, NULL, "FALSE", NULL, 3L, 0L, "a", "b", NULL, NULL, NULL)) stopifnot(length(grep(paste0("Error in 'git2r_diff': 'index' must be logical ", "vector of length one with non NA value\n"), res[[1]]$message)) > 0) ## Check various combinations of diff arguments res <- tools::assertError( .Call(git2r:::git2r_diff, NULL, NULL, tree(commits(repo)[[1]]), FALSE, NULL, 3L, 0L, "a", "b", NULL, NULL, NULL)) stopifnot(length(grep("Error in 'git2r_diff': Invalid diff parameters", res[[1]]$message)) > 0) res <- tools::assertError( .Call(git2r:::git2r_diff, NULL, NULL, tree(commits(repo)[[1]]), TRUE, NULL, 3L, 0L, "a", "b", NULL, NULL, NULL)) stopifnot(length(grep("Error in 'git2r_diff': Invalid diff parameters", res[[1]]$message)) > 0) res <- tools::assertError( .Call(git2r:::git2r_diff, repo, tree(commits(repo)[[1]]), NULL, FALSE, NULL, 3L, 0L, "a", "b", NULL, NULL, NULL)) stopifnot(length(grep("Error in 'git2r_diff': Invalid diff parameters", res[[1]]$message)) > 0) res <- tools::assertError( .Call(git2r:::git2r_diff, repo, tree(commits(repo)[[1]]), NULL, TRUE, NULL, 3L, 0L, "a", "b", NULL, NULL, NULL)) stopifnot(length(grep("Error in 'git2r_diff': Invalid diff parameters", res[[1]]$message)) > 0) res <- tools::assertError( .Call(git2r:::git2r_diff, repo, tree(commits(repo)[[1]]), tree(commits(repo)[[2]]), FALSE, NULL, 3L, 0L, "a", "b", NULL, NULL, NULL)) stopifnot(length(grep("Error in 'git2r_diff': Invalid diff parameters", res[[1]]$message)) > 0) res <- tools::assertError( .Call(git2r:::git2r_diff, repo, tree(commits(repo)[[1]]), tree(commits(repo)[[2]]), TRUE, NULL, 3L, 0L, "a", "b", NULL, NULL, NULL)) stopifnot(length(grep("Error in 'git2r_diff': Invalid diff parameters", res[[1]]$message)) > 0) ## TODO: printing ## Cleanup unlink(path, recursive = TRUE) git2r/tests/merge.R0000644000176200001440000001177314530613147013702 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library(git2r) source("util/check.R") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path, branch = "main") config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit writeLines("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", con = file.path(path, "test.txt")) add(repo, "test.txt") commit_1 <- commit(repo, "Commit message 1") ## Create first branch, checkout, add file and commit b_1 <- branch_create(commit_1, "branch1") checkout(b_1) writeLines("Branch 1", file.path(path, "branch-1.txt")) add(repo, "branch-1.txt") commit_2 <- commit(repo, "Commit message branch 1") ## Create second branch, checkout, add file and commit b_2 <- branch_create(commit_1, "branch2") checkout(b_2) writeLines("Branch 2", file.path(path, "branch-2.txt")) add(repo, "branch-2.txt") commit_3 <- commit(repo, "Commit message branch 2") writeLines(c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path, "test.txt")) add(repo, "test.txt") commit_4 <- commit(repo, "Second commit message branch 2") ## Check that merge base equals commit_1 stopifnot(identical(merge_base(commit_2, commit_3), commit_1)) ## Checkout main b <- branches(repo) checkout(b[sapply(b, "[", "name") == "main"][[1]], force = TRUE) ## Merge branch 1 m_1 <- merge(b[sapply(b, "[", "name") == "branch1"][[1]]) stopifnot(identical(m_1$fast_forward, TRUE)) stopifnot(identical(m_1$conflicts, FALSE)) stopifnot(identical(sha(m_1), NA_character_)) stopifnot(identical(print(m_1), m_1)) ## Merge branch 1 again m_1_again <- merge(b[sapply(b, "[", "name") == "branch1"][[1]]) stopifnot(identical(m_1_again$up_to_date, TRUE)) stopifnot(identical(m_1_again$fast_forward, FALSE)) stopifnot(identical(m_1_again$conflicts, FALSE)) stopifnot(identical(sha(m_1_again), NA_character_)) ## Merge branch 2 m_2 <- merge(b[sapply(b, "[", "name") == "branch2"][[1]]) stopifnot(identical(m_2$fast_forward, FALSE)) stopifnot(identical(m_2$conflicts, FALSE)) stopifnot(identical(sha(m_2), sha(commits(repo)[[1]]))) ## Create third branch, checkout, change file and commit b_3 <- branch_create(lookup(repo, sha(m_2)), "branch3") checkout(b_3) writeLines(c("Lorem ipsum dolor amet sit, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Commit message branch 3") ## Checkout main and create a change that creates a conflict on ## merge b <- branches(repo) checkout(b[sapply(b, "[", "name") == "main"][[1]], force = TRUE) writeLines(c("Lorem ipsum dolor sit amet, adipisicing consectetur elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Some commit message branch 1") ## Merge branch 3 with fail = TRUE m_3 <- merge(b[sapply(b, "[", "name") == "branch3"][[1]], fail = TRUE) stopifnot(identical(m_3$up_to_date, FALSE)) stopifnot(identical(m_3$fast_forward, FALSE)) stopifnot(identical(m_3$conflicts, TRUE)) stopifnot(identical(sha(m_3), NA_character_)) m_3 ## Check status; Expect to have a clean working directory wd <- structure(list(staged = empty_named_list(), unstaged = empty_named_list(), untracked = empty_named_list()), class = "git_status") stopifnot(identical(status(repo), wd)) ## Merge branch 3 m_3 <- merge(b[sapply(b, "[", "name") == "branch3"][[1]]) stopifnot(identical(m_3$up_to_date, FALSE)) stopifnot(identical(m_3$fast_forward, FALSE)) stopifnot(identical(m_3$conflicts, TRUE)) stopifnot(identical(sha(m_3), NA_character_)) m_3 ## Check status; Expect to have one unstaged unmerged conflict. stopifnot(identical(status(repo), structure(list(staged = empty_named_list(), unstaged = list(conflicted = "test.txt"), untracked = empty_named_list()), class = "git_status"))) ## Cleanup unlink(path, recursive = TRUE) git2r/tests/stash.R0000644000176200001440000000650014530613147013715 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2023 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. library("git2r") ## For debugging sessionInfo() libgit2_version() libgit2_features() ## Create a directory in tempdir path <- tempfile(pattern = "git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file writeLines("Hello world!", file.path(path, "test-1.txt")) ## add and commit add(repo, "test-1.txt") commit(repo, "Commit message") ## Pop stash writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test-1.txt")) stash(repo) stopifnot(identical("Hello world!", readLines(file.path(path, "test-1.txt")))) stash_pop(repo) stopifnot(identical(c("Hello world!", "HELLO WORLD!"), readLines(file.path(path, "test-1.txt")))) ## Make one more commit add(repo, "test-1.txt") commit(repo, "Next commit message") ## Check that there are no stashes stopifnot(identical(stash_list(repo), list())) ## Apply stash writeLines(c("Hello world!", "HELLO WORLD!", "hello world!"), file.path(path, "test-1.txt")) stash(repo) stopifnot(identical(c("Hello world!", "HELLO WORLD!"), readLines(file.path(path, "test-1.txt")))) stash_apply(repo) stopifnot(identical(c("Hello world!", "HELLO WORLD!", "hello world!"), readLines(file.path(path, "test-1.txt")))) stopifnot(identical(length(stash_list(repo)), 1L)) stash_drop(repo, 1) stopifnot(identical(stash_list(repo), list())) ## Make one more commit add(repo, "test-1.txt") commit(repo, "Apply stash commit message") ## Create one more file writeLines("Hello world!", file.path(path, "test-2.txt")) ## Check that there are no stashes stopifnot(identical(stash_list(repo), list())) ## Stash stash(repo) stopifnot(identical(stash_list(repo), list())) s <- stash(repo, untracked = TRUE) stopifnot(identical(print(s), s)) summary(s) stopifnot(identical(length(stash_list(repo)), 1L)) tree(stash_list(repo)[[1]]) ## Drop stash stash_drop(repo, 1) stopifnot(identical(stash_list(repo), list())) ## Check stash_drop argument tools::assertError(stash_drop(repo)) tools::assertError(stash_drop(repo, -1)) tools::assertError(stash_drop(repo, 0.5)) ## Create one more file writeLines("Hello world!", file.path(path, "test-3.txt")) ## Create stash in repository stash(repo, untracked = TRUE) stopifnot(identical(length(stash_list(repo)), 1L)) ## Check stash_list method with missing repo argument wd <- setwd(path) stopifnot(identical(length(stash_list()), 1L)) if (!is.null(wd)) setwd(wd) ## Drop git_stash object in repository stash_drop(stash_list(repo)[[1]]) ## Cleanup unlink(path, recursive = TRUE) git2r/MD50000644000176200001440000003440514705305562011626 0ustar liggesusers17ed4951a6f6e71ef1c123e03cb748db *DESCRIPTION dd4c2c35861925dce108b368fcf92628 *NAMESPACE 9d56557608e7f18d5d6ed4e99a74d4e3 *NEWS.md df2c5db027bb0061207107115e6ed015 *R/blame.R da2ac03a84e9ef85216a0ddedc603264 *R/blob.R 38ad0b89836d1440cba665d8bc3b7116 *R/branch.R 912d2f06cad541952b37731595598954 *R/bundle_r_package.R c0abc24a4d289ffeca34500d7e20c4e9 *R/checkout.R e2b0af52817ac5f65cf70a6fdb27b306 *R/commit.R 4ad875ff2745572c28c9aafbd58261ff *R/config.R b48d7b8d4765533e63278fe99a66985b *R/contributions.R 34746b1d15225b9794a802a89b7403c9 *R/credential.R 0d2cdd6cb40cbbe18319eb92104aebbc *R/diff.R dd12f6283cc298dbbaeb6d9616d4f699 *R/fetch.R f16c45511a05b6c55fe86cc63953cae1 *R/git2r.R b840a67a1a05e0767672bf2e785e1f9a *R/index.R fdb1fe4af8b086e024d8939a83c3c4b8 *R/libgit2.R 851bcdd1db21ea5217f8b8de50933ebb *R/merge.R 18fa6911662826fea4ae6b69924c5d63 *R/note.R 37bfdfce59ef1e0740ead6521d5ff0b4 *R/odb.R 952494199a5442d99f5fb21fe0b019bf *R/plot.R 864ef2e6b885e6954aeb667d4ad0806a *R/pull.R d69f5e41c8715f5db959208d525b2783 *R/punch_card.R 79c689da47fce42d0561112ef36b5dfd *R/push.R 85a7b050992e7a7b0ab1448846c21bbd *R/reference.R f87c3016938fbae9bd5427e98e860a0b *R/reflog.R d67cc1bee50828c079d4d31b38ea81be *R/refspec.R b5bc6fce04c6cc64d67ab27123e3e785 *R/remote.R 6843a62b27ce30414489e0b13a13239d *R/repository.R 9073616780e6b7a2f8cd3d67d12a2f24 *R/reset.R f0343193cd165e3012e3ca5a301e1ffe *R/revparse.R b1f5b6cf02fe9f3eb77f37de322bef3b *R/sha.R 696113f8caeb124de0c509b518943bba *R/signature.R fed6955ff4d64192dd45892459fa380d *R/stash.R 2d32df6eed00edeb874a15911a3e2865 *R/status.R 9d25661728bf7409cfa1e34e5f54b94b *R/tag.R 750282092d65155ddc7beb5728a6d951 *R/time.R e64d65d11ae86888b41621500482cfe3 *R/tree.R cb6c3d09641d6b9a2213578c13d2a8ce *R/when.R 58508b64e2bb8fa27681648b5d5ed98b *cleanup d37b7911cf890c7f37190286e6f1c042 *configure 023d1c419942cdf4f5ff81b47e2270a0 *configure.ac e7d754b87d85c9190fd5890b1f700854 *inst/COPYRIGHTS b331149fca2d7a121a72bedecf2b4deb *man/add.Rd d5267a2fa4c1dd6a4c19bc02b0ce3434 *man/ahead_behind.Rd 4f9de567ee9cd924e7a8b0c92c617ae5 *man/as.data.frame.git_repository.Rd 14791c824a3de0fc664e7753342414d8 *man/as.data.frame.git_tree.Rd c5da14f94fd7441d9368aff8446ecafd *man/as.list.git_tree.Rd 9409c8b875b52aaee969dc4e787d9aad *man/blame.Rd 15c60de0ebc7011960f78851ab2f4420 *man/blob_create.Rd 0f075ca210ecb7194407ff808670ad2c *man/branch_create.Rd e308c1de4bc95e056936de7e9d1c5018 *man/branch_delete.Rd 8e6b4f5cdc6f28109dcb5af77ceb66cd *man/branch_get_upstream.Rd 10740b906b8a05c8467ad243ba14f508 *man/branch_remote_name.Rd b8f9fd0a0a01cd8c3a162a238185c6ed *man/branch_remote_url.Rd b9050ab922f933324b19775eedca56fd *man/branch_rename.Rd 3949b2dd0e69a58e179a64c49b52a4b6 *man/branch_set_upstream.Rd 8f2fac4a8c84a16164d6a0a003ab9ae1 *man/branch_target.Rd dbc33c95c27a680f33526fbdf169abe3 *man/branches.Rd ed8ff151e968286185df78d45cc83bfe *man/bundle_r_package.Rd 03ab18767469316b997a26b1e32965e9 *man/checkout.Rd a8929e27f5921b7733f0137e0406387f *man/clone.Rd 39175724df5e169b629deaef431def06 *man/commit.Rd c518e42a71db69521a96f2b425dbde54 *man/commits.Rd 377b3ee874bfd019408521bc92826942 *man/config.Rd 5862c73ffa3182b1aaa27e5fcb35a618 *man/content.Rd 916c66ab567489629f260079e89117d0 *man/contributions.Rd f38a93b3884ca35938443e1fcef67385 *man/cred_env.Rd 2905f003036501cf8be6ecfb3936ebfa *man/cred_ssh_key.Rd a0c7163144fbd632bb4b315cee12ac8c *man/cred_token.Rd ca3a5483751a14780d2514530f78c353 *man/cred_user_pass.Rd c6a4941cf08cfe908fff2c9384f7c904 *man/default_signature.Rd 36796c3a8580c06fb5e62958233f4b8a *man/descendant_of.Rd 4d825c0e711d288b6c61a90747aa3557 *man/diff-methods.Rd 4cb82d68b325bbb580eec72b4d919ced *man/discover_repository.Rd 15413bac86f90043f7a9ce78005acf7f *man/fetch.Rd fd3a198a0bc7c4badd9b72df537e0ad4 *man/fetch_heads.Rd 0ecac4c06bda09e23527b07779e27bb7 *man/git2r.Rd 4e69c35a4cbbc009ad78c4a32b86b9a8 *man/git_config_files.Rd 3df60d437ea3ce712d837f4e9c9d4fe4 *man/git_time.Rd ef19202ae4f329968d55beb12f03cbfd *man/hash.Rd 0bb5696d8e70a6a60f2fbe9849cd3f8a *man/hashfile.Rd 3242f386a71929cd8d53a73d6e0fe96c *man/head.git_repository.Rd 3d817e50995bb65670ce134e777b3d72 *man/in_repository.Rd c5b3e61452ff6e296a4578cb8c5c923c *man/index_remove_bypath.Rd e5605585bdbe25fbbd04f785ed3aab7b *man/init.Rd cd85ef7784fad166d026729b621a25aa *man/is_bare.Rd cbbab70be97bfedd3494fa57140eb934 *man/is_binary.Rd 83517d2e86446b39c24679c56133e6e8 *man/is_blob.Rd 4c6d2b1c5e421ec9101e753a7c427152 *man/is_branch.Rd e1542a2e4ddd1d0918d33d1bdf372367 *man/is_commit.Rd c964e65abae418b7d709f9ccdc865d31 *man/is_detached.Rd ed9cfa42feb7e5231e39b34d6182b27e *man/is_empty.Rd 08a2a68b47f696eade54485d0f69b404 *man/is_head.Rd 4d37c8eb6de3ac2626fd3926a10f785e *man/is_local.Rd ab24429add3d56dbeeed3b81a6f20e67 *man/is_merge.Rd 4a0f5bb3ef3eeef0fbe97452d30d3fec *man/is_shallow.Rd b7a1f6bba46e39e04504037e0aa040d1 *man/is_tag.Rd 008c1a40f4f27053d1ffa9109d09c843 *man/is_tree.Rd a894855ebfa55bb79bac03227c9073f2 *man/last_commit.Rd 0cb99de7c8f70b73b743977613545109 *man/length.git_blob.Rd ee72b371ae4ec50c4bd2d004f39fd6b0 *man/length.git_diff.Rd 811d9a9de11579c753be15aac2560671 *man/length.git_tree.Rd 856072dcdfff2daca80283c38fd9b9b8 *man/libgit2_features.Rd f5b36b56e9898afc109a4167f2069167 *man/libgit2_version.Rd b698c5cb6b6c81da0e617764c495b3a6 *man/lookup.Rd b3c0dedeb66b768fc35cd4f4d4d83098 *man/lookup_commit.Rd 02c27b96ba7dcb4344b1405c05d74d13 *man/ls_tree.Rd 03d42586eef5535aa589177ee07ba360 *man/merge.Rd d3fc915175dc2c511f5b2c3d927b90a0 *man/merge_base.Rd 6343c8d7abb2a3d194319fb317afdfbd *man/note_create.Rd 1be9116c3be76656280d226f4765fcf3 *man/note_default_ref.Rd d32e381f70ba32cc11e21e80308611d1 *man/note_remove.Rd 2b80093593f380bc687f99b959a278c3 *man/notes.Rd 20c766579e5adc05e4497a68461ef56b *man/odb_blobs.Rd b77d0aab30c7cc08b6324beeea4dda70 *man/odb_objects.Rd 51f489dc8719c6b241d7daf174f7ffd9 *man/parents.Rd f5a07524bc918be81e40fdfc4a476304 *man/plot.git_repository.Rd ea0235e21065ff3f5d533184694d1081 *man/print.git_reflog_entry.Rd c0e7b2fb8ae792ca269ab7673d833d4e *man/pull.Rd 3d235431994af0b8a92aa9b00ef637b3 *man/punch_card.Rd ad93997dde39fbe5a21b240e71d65929 *man/push.Rd a02ce2d84f936ab1ae8154080f3a49f1 *man/reexports.Rd a4cdc735d5a0023d743c6a9ae4cd267a *man/references.Rd c1f0e3d0e911c4f4d00422cc5d99cf5d *man/reflog.Rd a6442cf9c888a63ce072a7b77b0177ce *man/remote_add.Rd d5b4f6525762a4cdf01c8b70e3e74c69 *man/remote_ls.Rd 1b6691fb52d638be4f44137234ba03eb *man/remote_remove.Rd 5ff725a2213ff83eb3aec0734b67b120 *man/remote_rename.Rd 8bd38203528c1b20f80bc26139ffadf3 *man/remote_set_url.Rd 8e66dbd022ef80e36eafdebf21aecf10 *man/remote_url.Rd 99c329f0d3fd299c5def2cc5a9e3768f *man/remotes.Rd 60cdfb2c9b60f9290f9d5e29564c4b2e *man/repository.Rd a232cb46703996c971c3a62eb79b6436 *man/repository_head.Rd 58b0b2d3dcf2e849dbd307ed6039f882 *man/reset.Rd a07c6d55e844daf3765257d8b8c24bff *man/revparse_single.Rd ec762f6d8b9e4c949323891f09f973f0 *man/rm_file.Rd cade2bb43df51c5bad476f08a1a3f952 *man/sha.Rd 7dc1454b285b1ccaca9e2d47eaa4bf96 *man/ssh_path.Rd dfb4cee2ca9b914e6632f1c7e86c1179 *man/ssl_cert_locations.Rd e3c124effca07b0412f98d27997575bc *man/stash.Rd ec288256c07afd75d77259b069b52506 *man/stash_apply.Rd cf67311200161cc4e1163910bb853a03 *man/stash_drop.Rd bd2f6f49b6eb3d967ea27bbb70f74dee *man/stash_list.Rd 239cd5748325f55bdcbce09a6a761d7f *man/stash_pop.Rd 4a4b3510bd2565b4e4e110b00b4adf24 *man/status.Rd 50feba2426bbc5044ba4fd5439e0fdea *man/sub-.git_tree.Rd fd1ae5b9d1290cde0147a7b0dcd25804 *man/summary.git_repository.Rd 8b0c34745c6a15f1dc7611fd062b3204 *man/summary.git_stash.Rd dda0ebd536d6ad0fc4ccfdefe87b6130 *man/summary.git_tree.Rd 27f8736fed19acc108c3056d7ad89293 *man/tag.Rd 690a8e5559addc2f81c3c9eb6830c013 *man/tag_delete.Rd df047e615d762624ec7cf191e8dee9d0 *man/tags.Rd 5916b74836adab701bdc0ce41925d0a5 *man/tree.Rd 00176ff4e69db4b137c54856c192957e *man/when.Rd ba3a1a4f454f3d9d5fc01c5a3b568c85 *man/workdir.Rd d11ff23e23383fef23dac36d2b92bc45 *src/Makevars.in d6ed6516c845ed860f5675fd227d48d1 *src/Makevars.win 4718460ae676f220fec2823b035cff18 *src/git2r-win.def 65951bc3c1c6de79a30800b025270bbc *src/git2r.c 4c2fc7c7753fec85dea399714239c9bb *src/git2r_S3.c 183ad80d4db8ce859f02791788a7a575 *src/git2r_S3.h c5b65af2b811d133f843dfe571704bc4 *src/git2r_arg.c bb13ede6c3df8bc1c9c5261d95b4a110 *src/git2r_arg.h ffcfb4db0567b6b800a3770aa4c8aa73 *src/git2r_blame.c 0590f03a2973f3b7ead4bfee123c1097 *src/git2r_blame.h ff6ed7ab8da415b01ba7f11505861089 *src/git2r_blob.c 4f2178aef4b5601c16ac09d9ab0360a6 *src/git2r_blob.h 700c50791f3927da7e15dfff6be94a0f *src/git2r_branch.c 7d8eedf2fdd2c55dcb6e05ed5c6f618a *src/git2r_branch.h a0ef863ed7be6d47b49cbb36cc68750f *src/git2r_checkout.c 89161937429aab6567363d9d4e59113d *src/git2r_checkout.h 678d80c1f34b5a89f950815e253b5262 *src/git2r_clone.c 76406656a419de911c6ddc3ad17b908d *src/git2r_clone.h 1c19a5327d5e38056aaf9e16c1c0a080 *src/git2r_commit.c 1a61abdcd5d7558ce07148454a9fe096 *src/git2r_commit.h e2c67a7bc2c488a0fb3c6f55e0c40bb7 *src/git2r_config.c 2a5cd9432062a0893957344f471503b5 *src/git2r_config.h 3c60d4ddd35d852d512558b873bbc7c4 *src/git2r_cred.c c799c137d1afb75ccf99555c2b1c761c *src/git2r_cred.h 9773e8b5f0d600ff45f2c16b49c434bd *src/git2r_diff.c a5c67c5ad4f9e0f6d9ebabc8ab230dd9 *src/git2r_diff.h 691a2d92648714d016bc445787a1aa2c *src/git2r_error.c faae4b9b347fc0143e19899527a15f99 *src/git2r_error.h 4d0d7ce2ddf435f953eadce0d5ae194f *src/git2r_graph.c c3a13beeacf07e857036cbe877d7dae9 *src/git2r_graph.h ef911860dfed7bc7ed1691491471aac7 *src/git2r_index.c 07277b9d8d7993129165ccf33ecd3b6b *src/git2r_index.h e94df7c7bae8d35e67e8cba9833ff59b *src/git2r_libgit2.c 5dc19c8872d38e8136b240417fec0a88 *src/git2r_libgit2.h e90d05d4c73f0d144c622d9f8723b4e5 *src/git2r_merge.c e9fabfe4d16bcc226f6a47f2b492ad95 *src/git2r_merge.h d580809a731a52d35ded6a0fc60bbe2b *src/git2r_note.c 00c8c66f54b30fac6733aad059256cdf *src/git2r_note.h a49ab05c11a58f625e7d428bfab02dcf *src/git2r_object.c 5cfce52edcef1af271df02583927c19e *src/git2r_object.h ebccbd624d2985eb24950e5a2e6b728c *src/git2r_odb.c 25046d116d8caa2140a277ec719c7856 *src/git2r_odb.h 4ddaf8afd7be13e7f8396b1e2ed08898 *src/git2r_oid.c c19b39cc1c34f5b3579a165d8f4973d6 *src/git2r_oid.h 7eb5cd724bc639aa846f72cdb20b50cd *src/git2r_push.c 9f877e9f2bb03fa3478acb19c55bd054 *src/git2r_push.h da2403ab0aee50ce069eaaf5a4577259 *src/git2r_reference.c 5803da458ac3c586000d7381f1f3c497 *src/git2r_reference.h dc1da66087bc1946017ed04f22722224 *src/git2r_reflog.c 8b6e7c2e4207bdb8490e4d3b5284cd67 *src/git2r_reflog.h 134769ba1ba421199dec71b64edda4db *src/git2r_remote.c ccdd219017dfc1dbf7304963dada6880 *src/git2r_remote.h 2293ebeaa5c9e1c3990fc43f4825460d *src/git2r_repository.c 31b03fe3a62562b1a34bd8c592c3a721 *src/git2r_repository.h 1ec1ab9931d310f6fd557cb79a09b2e7 *src/git2r_reset.c 1f1475f57ee2f1607cd65c99cf54c9b6 *src/git2r_reset.h b752589a4379f85256edc791f43c6328 *src/git2r_revparse.c a5605827f68d65572c28ac647cbf0f55 *src/git2r_revparse.h 03d2fee932a41bc8858be19903b77dad *src/git2r_revwalk.c 0530bdddca0a35a7dcba2f43d5699b19 *src/git2r_revwalk.h 0b1322ba06b7153fdd0063c6dbd6888d *src/git2r_signature.c c644c059e5a3755fd2a42cedd35e8d7e *src/git2r_signature.h c1daf3ce27ea5f8e53eb5c141b344b03 *src/git2r_stash.c 3e9721fb8188f18df721813efe34d6a7 *src/git2r_stash.h b43d7d43a5f5e2cb692446c42da229c2 *src/git2r_status.c bf57139eb87e930232eae7507ea17964 *src/git2r_status.h 0f4dc404067b324a9a09d5befe0f5761 *src/git2r_tag.c f8f7433e00e95aaf5719a476e8806ede *src/git2r_tag.h acb24142843eb89208929c5b03d11e01 *src/git2r_transfer.c bec24a9c75b395589630f783353b5021 *src/git2r_transfer.h a2cc5fdb0944f772d82914d3493ec480 *src/git2r_tree.c fca98773c5f867d7c6f98afe6a8e3a4e *src/git2r_tree.h 94715bccc202c9ae358a596f46cc4e07 *tests/add-force.R ca145a40a0d19ec643c22df84b23244c *tests/bare_repository.R f070eeafff28b9b08f909de8994a8cc6 *tests/blame.R e0d29880b0706d1a744b3aebde1a6853 *tests/blob.R 04d3f3dab26d525c0b62425e1de1401b *tests/branch.R c11f8d147abd9c9d472848fd54d79098 *tests/bundle.R b421358554b9e4f14917ac5de540ce15 *tests/checkout-named-branch.R 537ee0ea69261fb6eccb8ceacc00f728 *tests/checkout.R 42acf5ffe5b8dfd3cfcea35c9fc43094 *tests/checkout_branch.R 73b74ec3e625b0eca81a10774a7bfa8d *tests/checkout_commit.R cbafdba957f3d0a2b1f35e2de4cc4618 *tests/checkout_tag.R 4355dbc92b8252fac8fafa2df4775c10 *tests/clone_bare.R d2e0f2392c3bf36f264489b87354e54c *tests/clone_branch.R 78c29241c6a3f5ca6baadd8e1f5a11de *tests/clone_checkout.R e22ee124476925c772dd293bc586dd33 *tests/commit.R 1c786583e4646ec628bfa19d133d9705 *tests/commits_path.R e76102fa60fc6c5208c213fe00b89bb4 *tests/config.R c0e39f66362e6a1b97af4b5a9ee084ed *tests/diff.R b591af511e093f889ae013a4f8932042 *tests/fast_forward_merge.R 5a1d7b8b4579575ccbe4252b110facad *tests/fetch.R 53c09bd3f3f75ffe61b553522e8cbc80 *tests/graph.R 41291326a345d742fd2a82b31b4712d5 *tests/index.R 2470ef596481664817dcff6d5ca613f9 *tests/invalid-conf-var.R 12741f588de8be6b8dcd13ca9d8c0e51 *tests/libgit2.R 01936bf92b0a9e465074222dfc95240d *tests/ls_tree.R 09a9b413436a4b572f3bb11a3024b83a *tests/merge.R 24f5c9c8d3c113bb3442b75ae5fc2099 *tests/merge_named_branch.R 1dae778047e51f4047d94e5b3f1d835c *tests/normal_merge.R 468028a76164a910aadf2019ce0a0153 *tests/note.R 2b6278aded9a4efdd6d8f68b154d1958 *tests/odb_blobs.R f38bb0c542782ec36324d1d5d81c6970 *tests/pre-process-path.R dd46eec9103dddee0caafbc4ba88aa09 *tests/pull.R a5617fc797268b450127637be87081d1 *tests/push-force.R afc6809cc851d86131f717ee35a3bb00 *tests/push.R 53f67726af4171d49d32e7467fd30db5 *tests/reference.R 11379a7991a84cc60c6a8fa45510651b *tests/reflog.R 1e0d88b8e5c744bbae81078a66619714 *tests/refspec.R 33c28426a3b286232784f294286d04e7 *tests/remotes.R 81fb1ee94edbf1242f6d5acda7f5c11b *tests/remove.R fbd229df1cc53199f2711baf0ab44a75 *tests/repository.R 3763aa13d0a60e7886f43460260c7d6f *tests/reset.R c341af34a1e5899a876a25b43d7cf1c8 *tests/revparse.R f1e41724dd9eada8ad98cff4e79f6f3f *tests/signature.R 29743141c6dae398de3f7856aaab1abe *tests/stash.R 3c26ecbecce5ec66479e3c7ad076ee4d *tests/status.R ea14b19b40a27b05da4968533c8d5415 *tests/tag.R 11eea15650f06570ddf0372b5d793fdf *tests/time.R 0a40cd15e694b9fe711253a96df00b3c *tests/tree.R 8a4603d96c6d324f5cdef12f70715963 *tests/util/check.R 8c153f1850b1de2876bf04ffa0bcb12a *tests/when.R 7656db1151b730dc6c51cbfa83136071 *tools/config.guess f1d8f489b65ababc19b36bb9cc38670a *tools/config.rpath e55224754deb973527e64156e8c47acd *tools/config.sub f6b34e2198c1cf50c8038f5704f664c4 *tools/install-sh f56e89fee26d40334bb9a1474895b187 *tools/missing c497ed2a59f927f916cfd7edc62307cd *tools/pkg.m4 f0af14ae19ca3a7331e717eb0d6a606d *tools/version.c git2r/R/0000755000176200001440000000000014704742534011514 5ustar liggesusersgit2r/R/plot.R0000644000176200001440000000501313526222161012602 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2019 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Plot commits over time ##' ##' @param x The repository to plot ##' @param breaks Default is \code{month}. Change to year, quarter, ##' week or day as necessary. ##' @param main Default title for the plot is "Commits on repo:" and ##' repository workdir basename. Supply a new title if you desire one. ##' @param ... Additional arguments affecting the plot ##' @importFrom graphics axis ##' @importFrom graphics barplot ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- clone("https://github.com/ropensci/git2r.git", path) ##' ##' ## Plot commits ##' plot(repo) ##' } plot.git_repository <- function(x, breaks = c("month", "year", "quarter", "week", "day"), main = NULL, ...) { breaks <- match.arg(breaks) df <- contributions(x, breaks = breaks, by = "commits") tmp <- data.frame(when = seq(from = min(df$when), to = max(df$when), by = breaks), n = 0) i <- match(df$when, tmp$when) tmp$n[i] <- df$n df <- tmp xlab <- sprintf("Time [%s]", breaks) ylab <- "Number of commits" if (is.null(main)) { if (is_bare(x)) { main <- "Commits" } else { main <- sprintf("Commits on repository: %s", basename(workdir(x))) } } mp <- barplot(df$n, xlab = xlab, ylab = ylab, main = main, ...) axis(1, at = mp, labels = seq(min(df$when), max(df$when), breaks)) } git2r/R/branch.R0000644000176200001440000003635414704016153013076 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Create a branch ##' ##' @param commit Commit to which the branch should point. The default ##' is to use the \code{last_commit()} function to determine the ##' commit to which the branch should point. ##' @param name Name for the branch ##' @param force Overwrite existing branch. Default = FALSE ##' @return invisible git_branch object ##' @export ##' @useDynLib git2r git2r_branch_create ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' lines <- "Hello world!" ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "First commit message") ##' ##' ## Create a branch ##' branch_1 <- branch_create(commit_1, name = "test-branch") ##' ##' ## Add one more commit ##' lines <- c("Hello world!", "HELLO WORLD!") ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_2 <- commit(repo, "Another commit message") ##' ##' ## Create a branch with the same name should fail ##' try(branch_create(commit_2, name = "test-branch"), TRUE) ##' ##' ## Force it ##' branch_2 <- branch_create(commit_2, name = "test-branch", force = TRUE) ##' } branch_create <- function(commit = last_commit(), name = NULL, force = FALSE) { invisible(.Call(git2r_branch_create, name, commit, force)) } ##' Delete a branch ##' ##' @param branch The branch ##' @return invisible NULL ##' @export ##' @useDynLib git2r git2r_branch_delete ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "First commit message") ##' ##' ## Create a 'dev' branch ##' dev <- branch_create(commit_1, name = "dev") ##' branches(repo) ##' ##' ## Delete 'dev' branch ##' branch_delete(dev) ##' branches(repo) ##' } branch_delete <- function(branch = NULL) { .Call(git2r_branch_delete, branch) invisible(NULL) } ##' Remote name of a branch ##' ##' The name of remote that the remote tracking branch belongs to ##' @param branch The branch ##' @return character string with remote name ##' @export ##' @useDynLib git2r git2r_branch_remote_name ##' @examples ##' \dontrun{ ##' ## Initialize two temporary repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' dir.create(path_repo) ##' repo_bare <- init(path_bare, bare = TRUE) ##' repo <- clone(path_bare, path_repo) ##' ##' ## Config user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path_repo, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Push commits from repository to bare repository ##' ## Adds an upstream tracking branch to branch 'master' ##' push(repo, "origin", "refs/heads/master") ##' ##' ## Get remote name ##' branch_remote_name(branches(repo)[[2]]) ##' } branch_remote_name <- function(branch = NULL) { .Call(git2r_branch_remote_name, branch) } ##' Remote url of a branch ##' ##' @param branch The branch ##' @return character string with remote url ##' @export ##' @useDynLib git2r git2r_branch_remote_url ##' @examples ##' \dontrun{ ##' ## Initialize two temporary repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' dir.create(path_repo) ##' repo_bare <- init(path_bare, bare = TRUE) ##' repo <- clone(path_bare, path_repo) ##' ##' ## Config user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path_repo, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Push commits from repository to bare repository ##' ## Adds an upstream tracking branch to branch 'master' ##' push(repo, "origin", "refs/heads/master") ##' ##' ## Get remote url of tracking branch to branch 'master' ##' branch_remote_url(branch_get_upstream(repository_head(repo))) ##' } branch_remote_url <- function(branch = NULL) { .Call(git2r_branch_remote_url, branch) } ##' Rename a branch ##' ##' @param branch Branch to rename ##' @param name The new name for the branch ##' @param force Overwrite existing branch. Default is FALSE ##' @return invisible renamed \code{git_branch} object ##' @export ##' @useDynLib git2r git2r_branch_rename ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Config user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Rename 'master' branch to 'dev' ##' branches(repo) ##' branch_rename(repository_head(repo), "dev") ##' branches(repo) ##' } branch_rename <- function(branch = NULL, name = NULL, force = FALSE) { invisible(.Call(git2r_branch_rename, branch, name, force)) } ##' Get target (sha) pointed to by a branch ##' ##' @param branch The branch ##' @return sha or NA if not a direct reference ##' @export ##' @useDynLib git2r git2r_branch_target ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Config user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Get target (sha) pointed to by 'master' branch ##' branch_target(repository_head(repo)) ##' } branch_target <- function(branch = NULL) { .Call(git2r_branch_target, branch) } ##' Get remote tracking branch ##' ##' Get remote tracking branch, given a local branch. ##' @param branch The branch ##' @return \code{git_branch} object or NULL if no remote tracking ##' branch. ##' @export ##' @useDynLib git2r git2r_branch_get_upstream ##' @examples ##' \dontrun{ ##' ## Initialize two temporary repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' dir.create(path_repo) ##' repo_bare <- init(path_bare, bare = TRUE) ##' repo <- clone(path_bare, path_repo) ##' ##' ## Config user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path_repo, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Push commits from repository to bare repository ##' ## Adds an upstream tracking branch to branch 'master' ##' push(repo, "origin", "refs/heads/master") ##' ##' ## Get remote tracking branch ##' branch_get_upstream(repository_head(repo)) ##' } branch_get_upstream <- function(branch = NULL) { .Call(git2r_branch_get_upstream, branch) } ##' Set remote tracking branch ##' ##' Set the upstream configuration for a given local branch ##' @param branch The branch to configure ##' @param name remote-tracking or local branch to set as ##' upstream. Pass NULL to unset. ##' @return invisible NULL ##' @export ##' @useDynLib git2r git2r_branch_set_upstream ##' @examples ##' \dontrun{ ##' ## Initialize two temporary repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' dir.create(path_repo) ##' repo_bare <- init(path_bare, bare = TRUE) ##' repo <- clone(path_bare, path_repo) ##' ##' ## Config user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path_repo, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Push commits from repository to bare repository ##' ## Adds an upstream tracking branch to branch 'master' ##' push(repo, "origin", "refs/heads/master") ##' ##' ## Unset remote remote tracking branch ##' branch_get_upstream(repository_head(repo)) ##' branch_set_upstream(repository_head(repo), NULL) ##' branch_get_upstream(repository_head(repo)) ##' ##' ## Set remote tracking branch ##' branch_set_upstream(repository_head(repo), "origin/master") ##' branch_get_upstream(repository_head(repo)) ##' } branch_set_upstream <- function(branch = NULL, name) { if (missing(name)) stop("Missing argument name") .Call(git2r_branch_set_upstream, branch, name) invisible(NULL) } ##' Branches ##' ##' List branches in repository ##' @template repo-param ##' @param flags Filtering flags for the branch listing. Valid values ##' are 'all', 'local' or 'remote' ##' @return list of branches in repository ##' @export ##' @useDynLib git2r git2r_branch_list ##' @examples ##' \dontrun{ ##' ## Initialize repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' dir.create(path_repo) ##' repo_bare <- init(path_bare, bare = TRUE) ##' repo <- clone(path_bare, path_repo) ##' ##' ## Config first user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path_repo, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Push commits from repository to bare repository ##' ## Adds an upstream tracking branch to branch 'master' ##' push(repo, "origin", "refs/heads/master") ##' ##' ## List branches ##' branches(repo) ##' } branches <- function(repo = ".", flags=c("all", "local", "remote")) { flags <- switch(match.arg(flags), local = 1L, remote = 2L, all = 3L) .Call(git2r_branch_list, lookup_repository(repo), flags) } ##' Check if branch is head ##' ##' @param branch The branch \code{object} to check if it's head. ##' @return \code{TRUE} if branch is head, else \code{FALSE}. ##' @export ##' @useDynLib git2r git2r_branch_is_head ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## List branches ##' branches(repo) ##' ##' ## Check that 'master' is_head ##' master <- branches(repo)[[1]] ##' is_head(master) ##' ##' ## Create and checkout 'dev' branch ##' checkout(repo, "dev", create = TRUE) ##' ##' ## List branches ##' branches(repo) ##' ##' ## Check that 'master' is no longer head ##' is_head(master) ##' } is_head <- function(branch = NULL) { .Call(git2r_branch_is_head, branch) } ##' Check if branch is local ##' ##' @param branch The branch \code{object} to check if it's local ##' @return \code{TRUE} if branch is local, else \code{FALSE}. ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' dir.create(path_repo) ##' repo_bare <- init(path_bare, bare = TRUE) ##' repo <- clone(path_bare, path_repo) ##' ##' ## Config first user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path_repo, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Push commits from repository to bare repository ##' ## Adds an upstream tracking branch to branch 'master' ##' push(repo, "origin", "refs/heads/master") ##' ##' ## List branches ##' branches(repo) ##' ##' ## Check if first branch is_local ##' is_local(branches(repo)[[1]]) ##' ##' ## Check if second branch is_local ##' is_local(branches(repo)[[2]]) ##' } is_local <- function(branch) { if (!is_branch(branch)) stop("argument 'branch' must be a 'git_branch' object") identical(branch$type, 1L) } ##' @export print.git_branch <- function(x, ...) { sha <- branch_target(x) if (!is.na(sha)) { cat(sprintf("[%s] ", substr(sha, 1, 6))) } if (is_local(x)) { cat("(Local) ") } else { cat(sprintf("(%s @ %s) ", branch_remote_name(x), branch_remote_url(x))) } if (is_head(x)) { cat("(HEAD) ") } if (is_local(x)) { cat(sprintf("%s\n", x$name)) } else { cat(sprintf("%s\n", substr(x$name, start = nchar(branch_remote_name(x)) + 2, stop = nchar(x$name)))) } invisible(x) } ##' Check if object is \code{git_branch} ##' ##' @param object Check if object is of class \code{git_branch} ##' @return TRUE if object is class \code{git_branch}, else FALSE ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Commit a text file ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' branch <- branches(repo)[[1]] ##' ##' ## Check if branch ##' is_branch(branch) ##' } is_branch <- function(object) { inherits(object, "git_branch") } git2r/R/pull.R0000644000176200001440000001045514704120511012601 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Pull ##' ##' @template repo-param ##' @param credentials The credentials for remote repository ##' access. Default is NULL. To use and query an ssh-agent for the ##' ssh key credentials, let this parameter be NULL (the default). ##' @param merger Who made the merge, if the merge is non-fast forward ##' merge that creates a merge commit. The ##' \code{default_signature} for \code{repo} is used if this ##' parameter is \code{NULL}. ##' @template return-git_merge_result ##' @export ##' @useDynLib git2r git2r_merge_fetch_heads ##' @examples ##' \dontrun{ ##' ## Initialize repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo_1 <- tempfile(pattern="git2r-") ##' path_repo_2 <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' dir.create(path_repo_1) ##' dir.create(path_repo_2) ##' repo_bare <- init(path_bare, bare = TRUE) ##' repo_1 <- clone(path_bare, path_repo_1) ##' ##' ## Config first user and commit a file ##' config(repo_1, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path_repo_1, "example.txt")) ##' add(repo_1, "example.txt") ##' commit(repo_1, "First commit message") ##' ##' ## Push commits from first repository to bare repository ##' ## Adds an upstream tracking branch to branch 'master' ##' push(repo_1, "origin", "refs/heads/master") ##' ##' ## Clone to second repository ##' repo_2 <- clone(path_bare, path_repo_2) ##' config(repo_2, user.name = "Bob", user.email = "bob@@example.org") ##' ##' ## Change file and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path_repo_1, "example.txt")) ##' add(repo_1, "example.txt") ##' commit(repo_1, "Second commit message") ##' ##' ## Push commits from first repository to bare repository ##' push(repo_1) ##' ##' ## Pull changes to repo_2 ##' pull(repo_2) ##' ##' ## Change file again and commit. This time in repository 2 ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", ##' "minim veniam, quis nostrud exercitation ullamco laboris nisi ut") ##' writeLines(lines, file.path(path_repo_2, "example.txt")) ##' add(repo_2, "example.txt") ##' commit(repo_2, "Third commit message") ##' ##' ## Push commits from second repository to bare repository ##' push(repo_2) ##' ##' ## Pull changes to repo_1 ##' pull(repo_1) ##' ##' ## List commits in repositories ##' commits(repo_1) ##' commits(repo_2) ##' commits(repo_bare) ##' } pull <- function(repo = ".", credentials = NULL, merger = NULL) { repo <- lookup_repository(repo) if (is.null(merger)) merger <- default_signature(repo) current_branch <- repository_head(repo) if (is.null(current_branch)) stop("'branch' is NULL") if (!is_local(current_branch)) stop("'branch' is not local") upstream_branch <- branch_get_upstream(current_branch) if (is.null(upstream_branch)) stop("'branch' is not tracking a remote branch") fetch(repo = repo, name = branch_remote_name(upstream_branch), credentials = credentials) ## fetch heads marked for merge fh <- fetch_heads(repo) fh <- fh[vapply(fh, "[[", logical(1), "is_merge")] if (identical(length(fh), 0L)) stop("Remote ref was not fetched") .Call(git2r_merge_fetch_heads, fh, merger) } git2r/R/index.R0000644000176200001440000002044014704030003012723 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Add file(s) to index ##' ##' @template repo-param ##' @param path Character vector with file names or shell glob ##' patterns that will matched against files in the repository's ##' working directory. Each file that matches will be added to the ##' index (either updating an existing entry or adding a new ##' entry). ##' @param force Add ignored files. Default is FALSE. ##' @return invisible(NULL) ##' @export ##' @useDynLib git2r git2r_index_add_all ##' @examples ##' \dontrun{ ##' ## Initialize a repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file ##' writeLines("a", file.path(path, "a.txt")) ##' ##' ## Add file to repository and view status ##' add(repo, "a.txt") ##' status(repo) ##' ##' ## Add file with a leading './' when the repository working ##' ## directory is the current working directory ##' setwd(path) ##' writeLines("b", file.path(path, "b.txt")) ##' add(repo, "./b.txt") ##' status(repo) ##' ##' ## Add a file in a sub-folder with sub-folder as the working ##' ## directory. Create a file in the root of the repository ##' ## working directory that will remain untracked. ##' dir.create(file.path(path, "sub_dir")) ##' setwd("./sub_dir") ##' writeLines("c", file.path(path, "c.txt")) ##' writeLines("c", file.path(path, "sub_dir/c.txt")) ##' add(repo, "c.txt") ##' status(repo) ##' ##' ## Add files with glob expansion when the current working ##' ## directory is outside the repository's working directory. ##' setwd(tempdir()) ##' dir.create(file.path(path, "glob_dir")) ##' writeLines("d", file.path(path, "glob_dir/d.txt")) ##' writeLines("e", file.path(path, "glob_dir/e.txt")) ##' writeLines("f", file.path(path, "glob_dir/f.txt")) ##' writeLines("g", file.path(path, "glob_dir/g.md")) ##' add(repo, "glob_dir/*txt") ##' status(repo) ##' ##' ## Add file with glob expansion with a relative path when ##' ## the current working directory is inside the repository's ##' ## working directory. ##' setwd(path) ##' add(repo, "./glob_dir/*md") ##' status(repo) ##' } add <- function(repo = ".", path = NULL, force = FALSE) { ## Documentation for the pathspec argument in the libgit2 function ## 'git_index_add_all' that git2r use internally: ## ## The pathspec is a list of file names or shell glob patterns ## that will matched against files in the repository's working ## directory. Each file that matches will be added to the index ## (either updating an existing entry or adding a new entry). if (!is.character(path)) stop("'path' must be a character vector") repo <- lookup_repository(repo) repo_wd <- normalizePath(workdir(repo), winslash = "/") path <- vapply(path, sanitize_path, character(1), repo_wd = repo_wd) .Call(git2r_index_add_all, repo, path, isTRUE(force)) invisible(NULL) } sanitize_path <- function(p, repo_wd) { np <- suppressWarnings(normalizePath(p, winslash = "/")) if (!length(grep("/$", repo_wd))) repo_wd <- paste0(repo_wd, "/") ## Check if the normalized path is a non-file e.g. a glob. if (!file.exists(np)) { ## Check if the normalized path starts with a leading './' if (length(grep("^[.]/", np))) { nd <- suppressWarnings(normalizePath(dirname(p), winslash = "/")) if (!length(grep("/$", nd))) nd <- paste0(nd, "/") np <- paste0(nd, basename(np)) } } ## Check if the file is in the repository's working directory, ## else let libgit2 handle this path unmodified. if (!length(grep(paste0("^", repo_wd), np))) return(p) ## Change the path to be relative to the repository's working ## directory. Substitute common prefix with "" sub(paste0("^", repo_wd), "", np) } ##' Remove files from the working tree and from the index ##' ##' @template repo-param ##' @param path character vector with filenames to remove. Only files ##' known to Git are removed. ##' @return invisible(NULL) ##' @export ##' @useDynLib git2r git2r_index_remove_bypath ##' @examples ##' \dontrun{ ##' ## Initialize a repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file ##' writeLines("Hello world!", file.path(path, "file-to-remove.txt")) ##' ##' ## Add file to repository ##' add(repo, "file-to-remove.txt") ##' commit(repo, "First commit message") ##' ##' ## Remove file ##' rm_file(repo, "file-to-remove.txt") ##' ##' ## View status of repository ##' status(repo) ##' } rm_file <- function(repo = ".", path = NULL) { if (!is.character(path)) stop("'path' must be a character vector") repo <- lookup_repository(repo) if (length(path)) { repo_wd <- workdir(repo) repo_wd <- normalizePath(workdir(repo), winslash = "/") path <- vapply(path, sanitize_path, character(1), repo_wd = repo_wd) ## Check that files exists and are known to Git if (!all(file.exists(file.path(repo_wd, path)))) { stop(sprintf("pathspec '%s' did not match any files. ", path[!file.exists(file.path(repo_wd, path))])) } if (any(file.info(file.path(repo_wd, path))$isdir)) { stop(sprintf("pathspec '%s' did not match any files. ", path[exists(file.path(repo_wd, path))])) } s <- status(repo, staged = TRUE, unstaged = TRUE, untracked = TRUE, ignored = TRUE) if (any(path %in% c(s$ignored, s$untracked))) { stop(sprintf("pathspec '%s' did not match any files. ", path[path %in% c(s$ignored, s$untracked)])) } if (any(path %in% s$staged)) { stop(sprintf("'%s' has changes staged in the index. ", path[path %in% s$staged])) } if (any(path %in% s$unstaged)) { stop(sprintf("'%s' has local modifications. ", path[path %in% s$unstaged])) } ## Remove and stage files lapply(path, function(x) { file.remove(file.path(repo_wd, x)) .Call(git2r_index_remove_bypath, repo, x) }) } invisible(NULL) } ##' Remove an index entry corresponding to a file on disk ##' ##' @template repo-param ##' @param path character vector with filenames to remove. The path ##' must be relative to the repository's working folder. It may ##' exist. If this file currently is the result of a merge ##' conflict, this file will no longer be marked as ##' conflicting. The data about the conflict will be moved to the ##' "resolve undo" (REUC) section. ##' @return invisible(NULL) ##' @export ##' @useDynLib git2r git2r_index_remove_bypath ##' @examples ##' \dontrun{ ##' ## Initialize a repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file ##' writeLines("Hello world!", file.path(path, "file-to-remove.txt")) ##' ##' ## Add file to repository ##' add(repo, "file-to-remove.txt") ##' ##' ## View status of repository ##' status(repo) ##' ##' ## Remove file ##' index_remove_bypath(repo, "file-to-remove.txt") ##' ##' ## View status of repository ##' status(repo) ##' } index_remove_bypath <- function(repo = ".", path = NULL) { .Call(git2r_index_remove_bypath, lookup_repository(repo), path) invisible(NULL) } git2r/R/signature.R0000644000176200001440000000375314704030175013637 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Get the signature ##' ##' Get the signature according to the repository's configuration ##' @template repo-param ##' @return A \code{git_signature} object with entries: ## \describe{ ## \item{name}{ ## The full name of the author. ## } ## \item{email}{ ## Email of the author. ## } ## \item{when}{ ## Time when the action happened. ## } ## } ##' @export ##' @useDynLib git2r git2r_signature_default ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Get the default signature ##' default_signature(repo) ##' ##' ## Change user ##' config(repo, user.name = "Bob", user.email = "bob@@example.org") ##' ##' ## Get the default signature ##' default_signature(repo) ##' } default_signature <- function(repo = ".") { .Call(git2r_signature_default, lookup_repository(repo)) } ##' @export format.git_signature <- function(x, ...) { sprintf("name: %s\nemail: %s\nwhen: %s", x$name, x$email, as.character(x$when)) } ##' @export print.git_signature <- function(x, ...) { cat(format(x, ...), "\n", sep = "") invisible(x) } git2r/R/bundle_r_package.R0000644000176200001440000000441213556615027015105 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2018 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Bundle bare repo of package ##' ##' Clone the package git repository as a bare repository to ##' \code{pkg/inst/pkg.git} ##' @template repo-param ##' @return Invisible bundled \code{git_repository} object ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize repository ##' path <- tempfile() ##' dir.create(path) ##' path <- file.path(path, "git2r") ##' repo <- clone("https://github.com/ropensci/git2r.git", path) ##' ##' ## Bundle bare repository in package ##' bundle_r_package(repo) ##' ##' ## Build and install bundled package ##' wd <- setwd(dirname(path)) ##' system(sprintf("R CMD build %s", path)) ##' pkg <- list.files(".", pattern = "[.]tar[.]gz$") ##' system(sprintf("R CMD INSTALL %s", pkg)) ##' setwd(wd) ##' ##' ## Reload package ##' detach("package:git2r", unload = TRUE) ##' library(git2r) ##' ##' ## Summarize last five commits of bundled repo ##' repo <- repository(system.file("git2r.git", package = "git2r")) ##' invisible(lapply(commits(repo, n = 5), summary)) ##' ##' ## Plot content of bundled repo ##' plot(repo) ##' } bundle_r_package <- function(repo = ".") { repo <- lookup_repository(repo) ## Check for 'inst' folder inst <- file.path(workdir(repo), "inst") if (!isTRUE(file.info(inst)$isdir)) dir.create(inst) ## Check for 'pkg.git' folder local_path <- paste0(basename(workdir(repo)), ".git", sep = "") local_path <- file.path(inst, local_path) if (file.exists(local_path)) stop("Repo already exists:", local_path) invisible(clone(workdir(repo), local_path, bare = TRUE)) } git2r/R/repository.R0000644000176200001440000006507114704742461014066 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Coerce Git repository to a \code{data.frame} ##' ##' The commits in the repository are coerced to a \code{data.frame} ##' ##' ##' The \code{data.frame} have the following columns: ##' \describe{ ##' ##' \item{sha}{ ##' The 40 character hexadecimal string of the SHA-1 ##' } ##' ##' \item{summary}{ ##' the short "summary" of the git commit message. ##' } ##' ##' \item{message}{ ##' the full message of a commit ##' } ##' ##' \item{author}{ ##' full name of the author ##' } ##' ##' \item{email}{ ##' email of the author ##' } ##' ##' \item{when}{ ##' time when the commit happened ##' } ##' ##' } ##' @param x The repository \code{object} ##' @param ... Additional arguments. Not used. ##' @return \code{data.frame} ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create three files and commit ##' writeLines("First file", file.path(path, "example-1.txt")) ##' writeLines("Second file", file.path(path, "example-2.txt")) ##' writeLines("Third file", file.path(path, "example-3.txt")) ##' add(repo, "example-1.txt") ##' commit(repo, "Commit first file") ##' add(repo, "example-2.txt") ##' commit(repo, "Commit second file") ##' add(repo, "example-3.txt") ##' commit(repo, "Commit third file") ##' ##' ## Coerce commits to a data.frame ##' df <- as.data.frame(repo) ##' df ##' } as.data.frame.git_repository <- function(x, ...) { do.call("rbind", lapply(commits(x), as.data.frame)) } ##' Open a repository ##' ##' @param path A path to an existing local git repository. ##' @param discover Discover repository from path. Default is TRUE. ##' @return A \code{git_repository} object with entries: ##' \describe{ ##' \item{path}{ ##' Path to a git repository ##' } ##' } ##' @export ##' @useDynLib git2r git2r_repository_can_open ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' # Configure a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "test-1.txt")) ##' add(repo, 'test-1.txt') ##' commit_1 <- commit(repo, "Commit message") ##' ##' ## Make one more commit ##' writeLines(c("Hello world!", "HELLO WORLD!"), ##' file.path(path, "test-1.txt")) ##' add(repo, 'test-1.txt') ##' commit(repo, "Next commit message") ##' ##' ## Create one more file ##' writeLines("Hello world!", ##' file.path(path, "test-2.txt")) ##' ##' ## Brief summary of repository ##' repo ##' ##' ## Summary of repository ##' summary(repo) ##' ##' ## Workdir of repository ##' workdir(repo) ##' ##' ## Check if repository is bare ##' is_bare(repo) ##' ##' ## Check if repository is empty ##' is_empty(repo) ##' ##' ## Check if repository is a shallow clone ##' is_shallow(repo) ##' ##' ## List all references in repository ##' references(repo) ##' ##' ## List all branches in repository ##' branches(repo) ##' ##' ## Get HEAD of repository ##' repository_head(repo) ##' ##' ## Check if HEAD is head ##' is_head(repository_head(repo)) ##' ##' ## Check if HEAD is local ##' is_local(repository_head(repo)) ##' ##' ## List all tags in repository ##' tags(repo) ##' } repository <- function(path = ".", discover = TRUE) { if (isTRUE(discover)) { path <- discover_repository(path) if (is.null(path)) stop("The 'path' is not in a git repository") } else { path <- normalizePath(path, winslash = "/", mustWork = TRUE) if (!file.info(path)$isdir) stop("'path' is not a directory") } if (!isTRUE(.Call(git2r_repository_can_open, path))) stop("Unable to open repository at 'path'") structure(list(path = path), class = "git_repository") } ##' Init a repository ##' ##' @param path A path to where to init a git repository ##' @param bare If TRUE, a Git repository without a working directory ##' is created at the pointed path. If FALSE, provided path will ##' be considered as the working directory into which the .git ##' directory will be created. ##' @param branch Use the specified name for the initial branch in the ##' newly created repository. If \code{branch=NULL}, fall back to ##' the default name. ##' @return A \code{git_repository} object ##' @export ##' @useDynLib git2r git2r_repository_init ##' @seealso \link{repository} ##' @examples ##' \dontrun{ ##' ## Initialize a repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' is_bare(repo) ##' ##' ## Initialize a bare repository ##' path_bare <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' repo_bare <- init(path_bare, bare = TRUE) ##' is_bare(repo_bare) ##' } init <- function(path = ".", bare = FALSE, branch = NULL) { path <- normalizePath(path, winslash = "/", mustWork = TRUE) if (!file.info(path)$isdir) stop("'path' is not a directory") .Call(git2r_repository_init, path, bare, branch) repository(path) } ##' Clone a remote repository ##' ##' @param url The remote repository to clone ##' @param local_path Local directory to clone to. ##' @param bare Create a bare repository. Default is FALSE. ##' @param branch The name of the branch to checkout. Default is NULL ##' which means to use the remote's default branch. ##' @param checkout Checkout HEAD after the clone is complete. Default ##' is TRUE. ##' @param credentials The credentials for remote repository ##' access. Default is NULL. To use and query an ssh-agent for the ##' ssh key credentials, let this parameter be NULL (the default). ##' @param progress Show progress. Default is TRUE. ##' @return A \code{git_repository} object. ##' @seealso \link{repository}, \code{\link{cred_user_pass}}, ##' \code{\link{cred_ssh_key}} ##' @export ##' @useDynLib git2r git2r_clone ##' @examples ##' \dontrun{ ##' ## Initialize repository ##' path_repo_1 <- tempfile(pattern="git2r-") ##' path_repo_2 <- tempfile(pattern="git2r-") ##' dir.create(path_repo_1) ##' dir.create(path_repo_2) ##' repo_1 <- init(path_repo_1) ##' ##' ## Config user and commit a file ##' config(repo_1, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' writeLines( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' file.path(path_repo_1, "example.txt")) ##' add(repo_1, "example.txt") ##' commit(repo_1, "First commit message") ##' ##' ## Change file and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path_repo_1, "example.txt")) ##' add(repo_1, "example.txt") ##' commit(repo_1, "Second commit message") ##' ##' ## Change file again and commit. ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", ##' "minim veniam, quis nostrud exercitation ullamco laboris nisi ut") ##' writeLines(lines, file.path(path_repo_1, "example.txt")) ##' add(repo_1, "example.txt") ##' commit(repo_1, "Third commit message") ##' ##' ## Clone to second repository ##' repo_2 <- clone(path_repo_1, path_repo_2) ##' ##' ## List commits in repositories ##' commits(repo_1) ##' commits(repo_2) ##' } clone <- function(url = NULL, local_path = NULL, bare = FALSE, branch = NULL, checkout = TRUE, credentials = NULL, progress = TRUE) { .Call(git2r_clone, url, local_path, bare, branch, checkout, credentials, progress) repository(local_path) } ##' Get HEAD for a repository ##' ##' @param x The repository \code{x} to check head ##' @param ... Additional arguments. Unused. ##' @return NULL if unborn branch or not found. A git_branch if not a ##' detached head. A git_commit if detached head ##' @importFrom utils head ##' @export ##' @useDynLib git2r git2r_repository_head ##' @examples ##' \dontrun{ ##' ## Create and initialize a repository in a temporary directory ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "Commit message") ##' ##' ## Get HEAD of repository ##' repository_head(repo) ##' } head.git_repository <- function(x, ...) { .Deprecated("repository_head") .Call(git2r_repository_head, x) } ##' @export utils::head ##' Get HEAD for a repository ##' ##' @template repo-param ##' @return NULL if unborn branch or not found. A git_branch if not a ##' detached head. A git_commit if detached head ##' @export ##' @useDynLib git2r git2r_repository_head ##' @examples ##' \dontrun{ ##' ## Create and initialize a repository in a temporary directory ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "Commit message") ##' ##' ## Get HEAD of repository ##' repository_head(repo) ##' } repository_head <- function(repo = ".") { .Call(git2r_repository_head, lookup_repository(repo)) } ##' Check if repository is bare ##' ##' @template repo-param ##' @return \code{TRUE} if bare repository, else \code{FALSE} ##' @seealso \link{init} ##' @export ##' @useDynLib git2r git2r_repository_is_bare ##' @examples ##' \dontrun{ ##' ## Initialize a repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' is_bare(repo) ##' ##' ## Initialize a bare repository ##' path_bare <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' repo_bare <- init(path_bare, bare = TRUE) ##' is_bare(repo_bare) ##' } is_bare <- function(repo = ".") { .Call(git2r_repository_is_bare, lookup_repository(repo)) } ##' Check if HEAD of repository is detached ##' ##' @template repo-param ##' @return \code{TRUE} if repository HEAD is detached, else ##' \code{FALSE}. ##' @export ##' @useDynLib git2r git2r_repository_head_detached ##' @examples ##' \dontrun{ ##' ## Create and initialize a repository in a temporary directory ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "Commit message 1") ##' ##' ## Change file, add and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "Commit message 2") ##' ##' ## HEAD of repository is not detached ##' is_detached(repo) ##' ##' ## Checkout first commit ##' checkout(commit_1) ##' ##' ## HEAD of repository is detached ##' is_detached(repo) ##' } is_detached <- function(repo = ".") { .Call(git2r_repository_head_detached, lookup_repository(repo)) } ##' Check if repository is empty ##' ##' @template repo-param ##' @return \code{TRUE} if repository is empty else \code{FALSE}. ##' @export ##' @useDynLib git2r git2r_repository_is_empty ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Check if it's an empty repository ##' is_empty(repo) ##' ##' ## Commit a file ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Check if it's an empty repository ##' is_empty(repo) ##' } is_empty <- function(repo = ".") { .Call(git2r_repository_is_empty, lookup_repository(repo)) } ##' Determine if a directory is in a git repository ##' ##' The lookup start from path and walk across parent directories if ##' nothing has been found. ##' @param path The path to the directory. ##' @return TRUE if directory is in a git repository else FALSE ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Check if path is in a git repository ##' in_repository(path) ##' ##' ## Check if working directory is in a git repository ##' setwd(path) ##' in_repository() ##' } in_repository <- function(path = ".") { !is.null(discover_repository(path)) } ##' Determine if the repository is a shallow clone ##' ##' @template repo-param ##' @return \code{TRUE} if shallow clone, else \code{FALSE} ##' @export ##' @useDynLib git2r git2r_repository_is_shallow ##' @examples ##' \dontrun{ ##' ## Initialize repository ##' path_repo_1 <- tempfile(pattern="git2r-") ##' path_repo_2 <- tempfile(pattern="git2r-") ##' dir.create(path_repo_1) ##' dir.create(path_repo_2) ##' repo_1 <- init(path_repo_1) ##' ##' ## Config user and commit a file ##' config(repo_1, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path_repo_1, "example.txt")) ##' add(repo_1, "example.txt") ##' commit(repo_1, "First commit message") ##' ##' ## Change file and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path_repo_1, "example.txt")) ##' add(repo_1, "example.txt") ##' commit(repo_1, "Second commit message") ##' ##' ## Change file again and commit. ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", ##' "minim veniam, quis nostrud exercitation ullamco laboris nisi ut") ##' writeLines(lines, file.path(path_repo_1, "example.txt")) ##' add(repo_1, "example.txt") ##' commit(repo_1, "Third commit message") ##' ##' ## Clone to second repository ##' repo_2 <- clone(path_repo_1, path_repo_2) ##' ##' ## Check if it's a shallow clone ##' is_shallow(repo_2) ##' } is_shallow <- function(repo = ".") { .Call(git2r_repository_is_shallow, lookup_repository(repo)) } ##' Lookup ##' ##' Lookup one object in a repository. ##' @template repo-param ##' @param sha The identity of the object to lookup. Must be 4 to 40 ##' characters long. ##' @return a \code{git_blob} or \code{git_commit} or \code{git_tag} ##' or \code{git_tree} object ##' @export ##' @useDynLib git2r git2r_object_lookup ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "First commit message") ##' ##' ## Create tag ##' tag(repo, "Tagname", "Tag message") ##' ##' ## First, get SHAs to lookup in the repository ##' sha_commit <- sha(commit_1) ##' sha_tree <- sha(tree(commit_1)) ##' sha_blob <- sha(tree(commit_1)["example.txt"]) ##' sha_tag <- sha(tags(repo)[[1]]) ##' ##' ## SHAs ##' sha_commit ##' sha_tree ##' sha_blob ##' sha_tag ##' ##' ## Lookup objects ##' lookup(repo, sha_commit) ##' lookup(repo, sha_tree) ##' lookup(repo, sha_blob) ##' lookup(repo, sha_tag) ##' ##' ## Lookup objects, using only the first seven characters ##' lookup(repo, substr(sha_commit, 1, 7)) ##' lookup(repo, substr(sha_tree, 1, 7)) ##' lookup(repo, substr(sha_blob, 1, 7)) ##' lookup(repo, substr(sha_tag, 1, 7)) ##' } lookup <- function(repo = ".", sha = NULL) { .Call(git2r_object_lookup, lookup_repository(repo), sha) } ##' Lookup the commit related to a git object ##' ##' Lookup the commit related to a git_reference, git_tag or ##' git_branch object. ##' @param object a git object to get the related commit from. ##' @return A git commit object. ##' @export ##' @examples \dontrun{ ##' ## Create a directory in tempdir ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' ##' ## Initialize a repository ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, con = file.path(path, "test.txt")) ##' add(repo, "test.txt") ##' commit(repo, "Commit message 1") ##' ##' ## Get the commit pointed to by the 'master' branch ##' lookup_commit(repository_head(repo)) ##' ##' ## Create a tag ##' a_tag <- tag(repo, "Tagname", "Tag message") ##' ##' ## Get the commit pointed to by 'a_tag' ##' lookup_commit(a_tag) ##' } lookup_commit <- function(object) { UseMethod("lookup_commit", object) } ##' @rdname lookup_commit ##' @export lookup_commit.git_branch <- function(object) { lookup(object$repo, branch_target(object)) } ##' @rdname lookup_commit ##' @export lookup_commit.git_commit <- function(object) { object } ##' @rdname lookup_commit ##' @export lookup_commit.git_tag <- function(object) { lookup(object$repo, object$target) } ##' @rdname lookup_commit ##' @export lookup_commit.git_reference <- function(object) { lookup_commit(lookup(object$repo, object$sha)) } ##' @export print.git_repository <- function(x, ...) { if (any(is_empty(x), is.null(repository_head(x)))) { cat(sprintf("Local: %s\n", workdir(x))) cat("Head: nothing commited (yet)\n") } else { if (is_detached(x)) { cat(sprintf("Local: (detached) %s\n", workdir(x))) h <- repository_head(x) } else { cat(sprintf("Local: %s %s\n", repository_head(x)$name, workdir(x))) h <- repository_head(x) u <- branch_get_upstream(h) if (!is.null(u)) { rn <- branch_remote_name(u) cat(sprintf("Remote: %s @ %s (%s)\n", substr(u$name, nchar(rn) + 2, nchar(u$name)), rn, branch_remote_url(u))) } h <- lookup(x, branch_target(repository_head(x))) } cat(sprintf("Head: [%s] %s: %s\n", substring(h$sha, 1, 7), substring(as.character(h$author$when), 1, 10), h$summary)) } invisible(x) } ##' Summary of repository ##' ##' @param object The repository \code{object} ##' @param ... Additional arguments affecting the summary produced. ##' @return None (invisible 'NULL'). ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Config user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file ##' writeLines("Hello world!", file.path(path, "test.txt")) ##' summary(repo) ##' ##' ## Add file ##' add(repo, "test.txt") ##' summary(repo) ##' ##' ## Commit ##' commit(repo, "First commit message") ##' summary(repo) ##' ##' ## Change the file ##' writeLines(c("Hello again!", "Here is a second line", "And a third"), ##' file.path(path, "test.txt")) ##' summary(repo) ##' ##' ## Add file and commit ##' add(repo, "test.txt") ##' commit(repo, "Second commit message") ##' summary(repo) ##'} summary.git_repository <- function(object, ...) { print(object) cat("\n") n_branches <- sum(!is.na(unique(sapply(branches(object), branch_target)))) n_tags <- sum(!is.na(unique(vapply(tags(object), "[[", character(1), "sha")))) work <- commits(object) n_commits <- length(work) n_authors <- length(unique(vapply(lapply(work, "[[", "author"), "[[", character(1), "name"))) s <- .Call(git2r_status_list, object, TRUE, TRUE, TRUE, FALSE, TRUE) n_ignored <- length(s$ignored) n_untracked <- length(s$untracked) n_unstaged <- length(s$unstaged) n_staged <- length(s$staged) n_stashes <- length(stash_list(object)) ## Determine max characters needed to display numbers n <- max(vapply(c(n_branches, n_tags, n_commits, n_authors, n_stashes, n_ignored, n_untracked, n_unstaged, n_staged), nchar, numeric(1))) fmt <- paste0("Branches: %", n, "i\n", "Tags: %", n, "i\n", "Commits: %", n, "i\n", "Contributors: %", n, "i\n", "Stashes: %", n, "i\n", "Ignored files: %", n, "i\n", "Untracked files: %", n, "i\n", "Unstaged files: %", n, "i\n", "Staged files: %", n, "i\n") cat(sprintf(fmt, n_branches, n_tags, n_commits, n_authors, n_stashes, n_ignored, n_untracked, n_unstaged, n_staged)) cat("\nLatest commits:\n") lapply(commits(object, n = 5), print) invisible(NULL) } ## Strip trailing slash or backslash, unless it's the current drive ## root (/) or a Windows drive, for example, 'c:\'. strip_trailing_slash <- function(path) { if (!is.null(path) && grep("^(/|[a-zA-Z]:[/\\\\]?)$", path, invert = TRUE)) path <- sub("/?$", "", path) path } ##' Workdir of repository ##' ##' @template repo-param ##' @return Character vector with the path of the workdir. If the ##' repository is bare, \code{NULL} will be returned. ##' @export ##' @useDynLib git2r git2r_repository_workdir ##' @examples ##' \dontrun{ ##' ## Create a directory in tempdir ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' ##' ## Initialize a repository ##' repo <- init(path) ##' ##' ## Get the path of the workdir for repository ##' workdir(repo) ##' } workdir <- function(repo = ".") { path <- .Call(git2r_repository_workdir, lookup_repository(repo)) strip_trailing_slash(path) } ##' Find path to repository for any file ##' ##' @param path A character vector specifying the path to a file or ##' folder ##' @param ceiling The default is to not use the ceiling argument and ##' start the lookup from path and walk across parent ##' directories. When ceiling is 0, the lookup is only in ##' path. When ceiling is 1, the lookup is in both the path and ##' the parent to path. ##' @return Character vector with path (terminated by a file ##' separator) to repository or NULL if this cannot be ##' established. ##' @export ##' @useDynLib git2r git2r_repository_discover ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "example-1.txt")) ##' add(repo, "example-1.txt") ##' commit(repo, "First commit message") ##' ##' ## Create a second file. The file is not added for version control ##' ## in the repository. ##' dir.create(file.path(path, "example")) ##' file_2 <- file.path(path, "example/example-2.txt") ##' writeLines("Not under version control", file_2) ##' ##' ## Find the path to the repository using the path to the second file ##' discover_repository(file_2) ##' ##' ## Demonstrate the 'ceiling' argument ##' wd <- workdir(repo) ##' dir.create(file.path(wd, "temp")) ##' ##' ## Lookup repository in 'file.path(wd, "temp")'. Should return NULL ##' discover_repository(file.path(wd, "temp"), ceiling = 0) ##' ##' ## Lookup repository in parent to 'file.path(wd, "temp")'. ##' ## Should not return NULL ##' discover_repository(file.path(wd, "temp"), ceiling = 1) ##' } discover_repository <- function(path = ".", ceiling = NULL) { if (identical(path, ".")) path <- getwd() path <- normalizePath(path) if (!is.null(ceiling)) { ceiling <- as.integer(ceiling) if (identical(ceiling, 0L)) { ceiling <- dirname(path) } else if (identical(ceiling, 1L)) { ceiling <- dirname(dirname(path)) } else { stop("'ceiling' must be either 0 or 1") } } path <- .Call(git2r_repository_discover, path, ceiling) strip_trailing_slash(path) } ##' Internal utility function to lookup repository for methods ##' ##' @param repo repository \code{object} \code{git_repository}, or a ##' path to a repository, or \code{NULL}. If the \code{repo} ##' argument is \code{NULL}, the repository is searched for with ##' \code{\link{discover_repository}} in the current working ##' directory. ##' @return git_repository ##' @noRd lookup_repository <- function(repo = NULL) { if (is.null(repo) || identical(repo, ".")) { ## Try current working directory repo <- discover_repository(getwd()) if (is.null(repo)) stop("The working directory is not in a git repository") } else if (inherits(repo, "git_repository")) { return(repo) } repository(repo) } git2r/R/sha.R0000644000176200001440000000461213526223032012401 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2018 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Get the SHA-1 of a git object ##' ##' Get the 40 character hexadecimal string of the SHA-1. ##' @param object a git object to get the SHA-1 from. ##' @return The 40 character hexadecimal string of the SHA-1. ##' @export ##' @examples \dontrun{ ##' ## Create a directory in tempdir ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' ##' ## Initialize a repository ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "test.txt")) ##' add(repo, "test.txt") ##' commit(repo, "Commit message 1") ##' ##' ## Get the SHA-1 of the last commit ##' sha(last_commit(repo)) ##' } sha <- function(object) { UseMethod("sha", object) } ##' @rdname sha ##' @export sha.git_blob <- function(object) { object$sha } ##' @rdname sha ##' @export sha.git_branch <- function(object) { branch_target(object) } ##' @rdname sha ##' @export sha.git_commit <- function(object) { object$sha } ##' @rdname sha ##' @export sha.git_note <- function(object) { object$sha } ##' @rdname sha ##' @export sha.git_reference <- function(object) { object$sha } ##' @rdname sha ##' @export sha.git_reflog_entry <- function(object) { object$sha } ##' @rdname sha ##' @export sha.git_tag <- function(object) { object$sha } ##' @rdname sha ##' @export sha.git_tree <- function(object) { object$sha } ##' @rdname sha ##' @export sha.git_fetch_head <- function(object) { object$sha } ##' @rdname sha ##' @export sha.git_merge_result <- function(object) { object$sha } git2r/R/tag.R0000644000176200001440000001420214704031341012374 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Create tag targeting HEAD commit in repository ##' ##' @param object The repository \code{object}. ##' @param name Name for the tag. ##' @param message The tag message. Specify a tag message to create an ##' annotated tag. A lightweight tag is created if the message ##' parameter is \code{NULL}. ##' @param session Add sessionInfo to tag message. Default is FALSE. ##' @param tagger The tagger (author) of the tag ##' @param force Overwrite existing tag. Default = FALSE ##' @return invisible(\code{git_tag}) object ##' @export ##' @useDynLib git2r git2r_tag_create ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Commit a text file ##' filename <- file.path(path, "example.txt") ##' writeLines("Hello world!", filename) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Create an annotated tag ##' tag(repo, "v1.0", "Tag message") ##' ##' ## List tags ##' tags(repo) ##' ##' ## Make a change to the text file and commit. ##' writeLines(c("Hello world!", "HELLO WORLD!"), filename) ##' add(repo, "example.txt") ##' commit(repo, "Second commit message") ##' ##' ## Create a lightweight tag ##' tag(repo, "v2.0") ##' ##' ## List tags ##' tags(repo) ##' } tag <- function(object = ".", name = NULL, message = NULL, session = FALSE, tagger = NULL, force = FALSE) { object <- lookup_repository(object) if (isTRUE(session)) message <- add_session_info(message) if (is.null(tagger)) tagger <- default_signature(object) invisible(.Call(git2r_tag_create, object, name, message, tagger, force)) } ##' Check if object is a git_tag object ##' ##' @param object Check if object is a git_tag object ##' @return TRUE if object is a git_tag, else FALSE ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Commit a text file ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Create tag ##' tag(repo, "Tagname", "Tag message") ##' ##' is_tag(tags(repo)[[1]]) ##' is_tag(last_commit(repo)) ##' } is_tag <- function(object) { inherits(object, "git_tag") } ##' Delete an existing tag reference ##' ##' @param object Can be either the path (default is ".") to a ##' repository, or a \code{git_repository} object, or a ##' \code{git_tag} object. or the tag name. ##' @param name If the \code{object} argument is a path to a ##' repository or a \code{git_repository}, the name of the tag to ##' delete. ##' @return \code{invisible(NULL)} ##' @export ##' @useDynLib git2r git2r_tag_delete ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Commit a text file ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Create two tags ##' tag(repo, "Tag1", "Tag message 1") ##' t2 <- tag(repo, "Tag2", "Tag message 2") ##' ##' ## List the two tags in the repository ##' tags(repo) ##' ##' ## Delete the two tags in the repository ##' tag_delete(repo, "Tag1") ##' tag_delete(t2) ##' ##' ## Show the empty list with tags in the repository ##' tags(repo) ##' } tag_delete <- function(object = ".", name = NULL) { if (is_tag(object)) { name <- object$name object <- object$repo } else { object <- lookup_repository(object) } .Call(git2r_tag_delete, object, name) invisible(NULL) } ##' Tags ##' ##' @template repo-param ##' @return list of tags in repository ##' @export ##' @useDynLib git2r git2r_tag_list ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Commit a text file ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Create tag ##' tag(repo, "Tagname", "Tag message") ##' ##' ## List tags ##' tags(repo) ##' } tags <- function(repo = ".") { .Call(git2r_tag_list, lookup_repository(repo)) } ##' @export format.git_tag <- function(x, ...) { sprintf("[%s] %s", substr(x$target, 1, 6), x$name) } ##' @export print.git_tag <- function(x, ...) { cat(format(x, ...), "\n", sep = "") invisible(x) } ##' @export summary.git_tag <- function(object, ...) { cat(sprintf(paste0("name: %s\n", "target: %s\n", "tagger: %s <%s>\n", "when: %s\n", "message: %s\n"), object$name, object$target, object$tagger$name, object$tagger$email, as.character(object$tagger$when), object$message)) } git2r/R/remote.R0000644000176200001440000001102314704026344013121 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Get the configured remotes for a repo ##' ##' @template repo-param ##' @return Character vector with remotes ##' @export ##' @useDynLib git2r git2r_remote_list ##' @template remote-example remotes <- function(repo = ".") { .Call(git2r_remote_list, lookup_repository(repo)) } ##' Add a remote to a repo ##' ##' @template repo-param ##' @param name Short name of the remote repository ##' @param url URL of the remote repository ##' @return NULL, invisibly ##' @export ##' @useDynLib git2r git2r_remote_add ##' @template remote-example remote_add <- function(repo = ".", name = NULL, url = NULL) { .Call(git2r_remote_add, lookup_repository(repo), name, url) invisible(NULL) } ##' Rename a remote ##' ##' @template repo-param ##' @param oldname Old name of the remote ##' @param newname New name of the remote ##' @return NULL, invisibly ##' @export ##' @useDynLib git2r git2r_remote_rename ##' @template remote-example remote_rename <- function(repo = ".", oldname = NULL, newname = NULL) { .Call(git2r_remote_rename, lookup_repository(repo), oldname, newname) invisible(NULL) } ##' Remove a remote ##' ##' All remote-tracking branches and configuration settings for the ##' remote will be removed. ##' @template repo-param ##' @param name The name of the remote to remove ##' @return NULL, invisibly ##' @export ##' @useDynLib git2r git2r_remote_remove ##' @template remote-example remote_remove <- function(repo = ".", name = NULL) { .Call(git2r_remote_remove, lookup_repository(repo), name) invisible(NULL) } ##' Set the remote's url in the configuration ##' ##' This assumes the common case of a single-url remote and will ##' otherwise raise an error. ##' @template repo-param ##' @param name The name of the remote ##' @param url The \code{url} to set ##' @return NULL, invisibly ##' @export ##' @useDynLib git2r git2r_remote_set_url ##' @template remote-example remote_set_url <- function(repo = ".", name = NULL, url = NULL) { .Call(git2r_remote_set_url, lookup_repository(repo), name, url) invisible(NULL) } ##' Get the remote url for remotes in a repo ##' ##' @template repo-param ##' @param remote Character vector with the remotes to get the url ##' from. Default is the remotes of the repository. ##' @return Character vector with remote_url for each of the remote ##' @export ##' @useDynLib git2r git2r_remote_url ##' @template remote-example remote_url <- function(repo = ".", remote = NULL) { repo <- lookup_repository(repo) if (is.null(remote)) remote <- remotes(repo) .Call(git2r_remote_url, repo, remote) } ##' List references in a remote repository ##' ##' Displays references available in a remote repository along with ##' the associated commit IDs. Akin to the 'git ls-remote' command. ##' @param name Character vector with the "remote" repository URL to ##' query or the name of the remote if a \code{repo} argument is ##' given. ##' @param repo an optional repository object used if remotes are ##' specified by name. ##' @param credentials The credentials for remote repository ##' access. Default is NULL. To use and query an ssh-agent for the ##' ssh key credentials, let this parameter be NULL (the default). ##' @return Character vector for each reference with the associated ##' commit IDs. ##' @export ##' @useDynLib git2r git2r_remote_ls ##' @examples ##' \dontrun{ ##' remote_ls("https://github.com/ropensci/git2r") ##' } remote_ls <- function(name = NULL, repo = NULL, credentials = NULL) { if (is.null(repo)) { ver <- libgit2_version() if (ver$major == 0 && ver$minor < 27) { path <- tempdir() repo <- init(path) on.exit(unlink(file.path(path, ".git"), recursive = TRUE)) } } else { repo <- lookup_repository(repo) } .Call(git2r_remote_ls, name, repo, credentials) } git2r/R/git2r.R0000644000176200001440000000211014704011362012644 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' git2r: R bindings to the libgit2 library ##' ##' git2r: R bindings to the libgit2 library. ##' @aliases git2r-package ##' @name git2r "_PACKAGE" ##' Unload hook function ##' ##' @param libpath A character string giving the complete path to the ##' package. ##' @noRd .onUnload <- function(libpath) { library.dynam.unload("git2r", libpath) } git2r/R/odb.R0000644000176200001440000001006514704114027012373 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Blobs in the object database ##' ##' List all blobs reachable from the commits in the object ##' database. For each commit, list blob's in the commit tree and ##' sub-trees. ##' @template repo-param ##' @return A data.frame with the following columns: ##' \describe{ ##' \item{sha}{The sha of the blob} ##' \item{path}{The path to the blob from the tree and sub-trees} ##' \item{name}{The name of the blob from the tree that contains the blob} ##' \item{len}{The length of the blob} ##' \item{commit}{The sha of the commit} ##' \item{author}{The author of the commit} ##' \item{when}{The timestamp of the author signature in the commit} ##' } ##' @note A blob sha can have several entries ##' @export ##' @useDynLib git2r git2r_odb_blobs ##' @examples \dontrun{ ##' ## Create a directory in tempdir ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' ##' ## Initialize a repository ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "test.txt")) ##' add(repo, "test.txt") ##' commit(repo, "Commit message 1") ##' ##' ## Change file and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path, "test.txt")) ##' add(repo, "test.txt") ##' commit(repo, "Commit message 2") ##' ##' ## Commit same content under different name in a sub-directory ##' dir.create(file.path(path, "sub-directory")) ##' file.copy(file.path(path, "test.txt"), ##' file.path(path, "sub-directory", "copy.txt")) ##' add(repo, "sub-directory/copy.txt") ##' commit(repo, "Commit message 3") ##' ##' ## List blobs ##' odb_blobs(repo) ##' } odb_blobs <- function(repo = ".") { blobs <- .Call(git2r_odb_blobs, lookup_repository(repo)) blobs <- data.frame(blobs, stringsAsFactors = FALSE) blobs <- blobs[order(blobs$when), ] index <- paste0(blobs$sha, ":", blobs$path, "/", blobs$name) blobs <- blobs[!duplicated(index), ] rownames(blobs) <- NULL blobs$when <- as.POSIXct(blobs$when, origin = "1970-01-01", tz = "GMT") blobs } ##' List all objects available in the database ##' ##' @template repo-param ##' @return A data.frame with the following columns: ##' \describe{ ##' \item{sha}{The sha of the object} ##' \item{type}{The type of the object} ##' \item{len}{The length of the object} ##' } ##' @export ##' @useDynLib git2r git2r_odb_objects ##' @examples \dontrun{ ##' ## Create a directory in tempdir ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' ##' ## Initialize a repository ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "test.txt")) ##' add(repo, "test.txt") ##' commit(repo, "Commit message 1") ##' ##' ## Create tag ##' tag(repo, "Tagname", "Tag message") ##' ##' ## List objects in repository ##' odb_objects(repo) ##' } odb_objects <- function(repo = ".") { data.frame(.Call(git2r_odb_objects, lookup_repository(repo)), stringsAsFactors = FALSE) } git2r/R/reflog.R0000644000176200001440000000641014704121130013075 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' List and view reflog information ##' ##' @template repo-param ##' @param refname The name of the reference to list. 'HEAD' by ##' default. ##' @return S3 class \code{git_reflog} with git_reflog_entry objects. ##' @export ##' @useDynLib git2r git2r_reflog_list ##' @examples ##' \dontrun{ ##' ## Initialize a repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Config user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Change file and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "Second commit message") ##' ##' ## Change file again and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", ##' "minim veniam, quis nostrud exercitation ullamco laboris nisi ut") ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "Third commit message") ##' ##' ## View reflog ##' reflog(repo) ##' } reflog <- function(repo = ".", refname = "HEAD") { structure(.Call(git2r_reflog_list, lookup_repository(repo), refname), class = "git_reflog") } ##' @export print.git_reflog <- function(x, ...) { lapply(x, print) invisible(x) } ##' Print a reflog entry ##' ##' @param x The reflog entry ##' @param ... Unused ##' @return None (invisible 'NULL'). ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## View repository HEAD reflog ##' reflog(repo) ##' } print.git_reflog_entry <- function(x, ...) { cat(sprintf("[%s] %s@{%i}: %s\n", substring(x$sha, 1, 7), x$refname, x$index, x$message)) invisible(x) } git2r/R/revparse.R0000644000176200001440000000406314704113522013456 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Revparse ##' ##' Find object specified by revision. ##' @template repo-param ##' @param revision The revision string, see ##' http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions ##' @return a \code{git_commit} or \code{git_tag} or \code{git_tree} ##' object ##' @export ##' @useDynLib git2r git2r_revparse_single ##' @examples ##' \dontrun{ ##' ## Create a directory in tempdir ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' ##' ## Initialize a repository ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "test.txt")) ##' add(repo, "test.txt") ##' commit(repo, "First commit message") ##' ##' # Change file and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path, "test.txt")) ##' add(repo, "test.txt") ##' commit(repo, "Second commit message") ##' ##' revparse_single(repo, "HEAD^") ##' revparse_single(repo, "HEAD:test.txt") ##' } revparse_single <- function(repo = ".", revision = NULL) { .Call(git2r_revparse_single, lookup_repository(repo), revision) } git2r/R/checkout.R0000644000176200001440000002033714704116007013437 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Determine previous branch name ##' ##' @param repo The repository. ##' @noRd previous_branch_name <- function(repo) { branch <- revparse_single(repo, "@{-1}")$sha branch <- sapply(references(repo), function(x) { if (is.null(x$sha)) return(NA_character_) if (x$sha == branch) return(x$shorthand) NA_character_ }) branch <- branch[vapply(branch, Negate(is.na), logical(1))] branch <- sapply(branches(repo, "local"), function(x) { ifelse(x$name %in% branch, x$name, NA_character_) }) branch <- branch[vapply(branch, Negate(is.na), logical(1))] if (any(!is.character(branch), !identical(length(branch), 1L))) { stop("'branch' must be a character vector of length one") } branch } ##' @useDynLib git2r git2r_checkout_tree ##' @useDynLib git2r git2r_repository_set_head ##' @noRd checkout_branch <- function(object, force) { ref_name <- paste0("refs/heads/", object$name) .Call(git2r_checkout_tree, object$repo, ref_name, force) .Call(git2r_repository_set_head, object$repo, ref_name) } ##' @useDynLib git2r git2r_checkout_tree ##' @useDynLib git2r git2r_repository_set_head_detached ##' @noRd checkout_commit <- function(object, force) { .Call(git2r_checkout_tree, object$repo, object$sha, force) .Call(git2r_repository_set_head_detached, object) } ##' @useDynLib git2r git2r_checkout_tree ##' @useDynLib git2r git2r_repository_set_head_detached ##' @noRd checkout_tag <- function(object, force) { .Call(git2r_checkout_tree, object$repo, object$target, force) .Call(git2r_repository_set_head_detached, lookup(object$repo, object$target)) } checkout_git_object <- function(object, force) { if (is_branch(object)) { checkout_branch(object, force) return(TRUE) } if (is_commit(object)) { checkout_commit(object, force) return(TRUE) } if (is_tag(object)) { checkout_tag(object, force) return(TRUE) } FALSE } ##' Checkout ##' ##' Update files in the index and working tree to match the content of ##' the tree pointed at by the treeish object (commit, tag or tree). ##' The default checkout strategy (\code{force = FALSE}) will only ##' make modifications that will not lose changes. Use \code{force = ##' TRUE} to force working directory to look like index. ##' @param object A path to a repository, or a \code{git_repository} ##' object, or a \code{git_commit} object, or a \code{git_tag} ##' object, or a \code{git_tree} object. ##' @param branch name of the branch to check out. Only used if object ##' is a path to a repository or a \code{git_repository} object. ##' @param create create branch if it doesn't exist. Only used if ##' object is a path to a repository or a \code{git_repository} ##' object. ##' @param force If \code{TRUE}, then make working directory match ##' target. This will throw away local changes. Default is ##' \code{FALSE}. ##' @param path Limit the checkout operation to only certain ##' paths. This argument is only used if branch is NULL. Default ##' is \code{NULL}. ##' @param ... Additional arguments. Not used. ##' @return invisible NULL ##' @export ##' @useDynLib git2r git2r_checkout_path ##' @useDynLib git2r git2r_repository_set_head ##' @examples ##' \dontrun{ ##' ## Create directories and initialize repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo_1 <- tempfile(pattern="git2r-") ##' path_repo_2 <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' dir.create(path_repo_1) ##' dir.create(path_repo_2) ##' repo_bare <- init(path_bare, bare = TRUE) ##' ##' ## Clone to repo 1 and config user ##' repo_1 <- clone(path_bare, path_repo_1) ##' config(repo_1, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Add changes to repo 1 and push to bare ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path_repo_1, "test.txt")) ##' add(repo_1, "test.txt") ##' commit(repo_1, "First commit message") ##' push(repo_1, "origin", "refs/heads/master") ##' ##' ## Create and checkout 'dev' branch in repo 1 ##' checkout(repo_1, "dev", create = TRUE) ##' ##' ## Add changes to 'dev' branch in repo 1 and push to bare ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path_repo_1, "test.txt")) ##' add(repo_1, "test.txt") ##' commit(repo_1, "Second commit message") ##' push(repo_1, "origin", "refs/heads/dev") ##' ##' ## Clone to repo 2 ##' repo_2 <- clone(path_bare, path_repo_2) ##' config(repo_2, user.name = "Bob", user.email = "bob@@example.org") ##' ##' ## Read content of 'test.txt' ##' readLines(file.path(path_repo_2, "test.txt")) ##' ##' ## Checkout dev branch ##' checkout(repo_2, "dev") ##' ##' ## Read content of 'test.txt' ##' readLines(file.path(path_repo_2, "test.txt")) ##' ##' ## Edit "test.txt" in repo_2 ##' writeLines("Hello world!", con = file.path(path_repo_2, "test.txt")) ##' ##' ## Check status ##' status(repo_2) ##' ##' ## Checkout "test.txt" ##' checkout(repo_2, path = "test.txt") ##' ##' ## Check status ##' status(repo_2) ##' } checkout <- function(object = NULL, branch = NULL, create = FALSE, force = FALSE, path = NULL, ...) { if (checkout_git_object(object, force)) return(invisible(NULL)) object <- lookup_repository(object) if (is.null(branch)) { if (is.null(path)) stop("missing 'branch' or 'path' argument") .Call(git2r_checkout_path, object, path) return(invisible(NULL)) } if (!is.character(branch) || !identical(length(branch), 1L)) stop("'branch' must be a character vector of length one") if (is_empty(object)) { if (!isTRUE(create)) stop(sprintf("'%s' did not match any branch", branch)) ref_name <- paste0("refs/heads/", branch) .Call(git2r_repository_set_head, object, ref_name) return(invisible(NULL)) } if (identical(branch, "-")) branch <- previous_branch_name(object) ## Check if branch exists in a local branch lb <- branches(object, "local") lb <- lb[vapply(lb, "[[", character(1), "name") == branch] if (length(lb)) { checkout_branch(lb[[1]], force) return(invisible(NULL)) } ## Check if there exists exactly one remote branch with a matching ## name. rb <- branches(object, "remote") ## Split remote/name to check for a unique name name <- vapply(rb, function(x) { remote <- strsplit(x$name, "/")[[1]][1] sub(paste0("^", remote, "/"), "", x$name) }, character(1)) i <- which(name == branch) if (identical(length(i), 1L)) { ## Create branch and track remote commit <- lookup(object, branch_target(rb[[i]])) branch <- branch_create(commit, branch) branch_set_upstream(branch, rb[[i]]$name) checkout_branch(branch, force) return(invisible(NULL)) } if (isTRUE(create)) { ## Create branch commit <- lookup(object, branch_target(repository_head(object))) checkout_branch(branch_create(commit, branch), force) return(invisible(NULL)) } ## Check if branch object is specified by revision. if (checkout_git_object(revparse_single(object, branch), force)) return(invisible(NULL)) stop(sprintf("'%s' did not match any branch", branch)) } git2r/R/libgit2.R0000644000176200001440000000363714704017205013172 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Compile time options for libgit2. ##' ##' @return A list with threads, https and ssh set to TRUE/FALSE. ##' @keywords methods ##' @export ##' @useDynLib git2r git2r_libgit2_features ##' @examples ##' libgit2_features() libgit2_features <- function() { .Call(git2r_libgit2_features) } ##' Version of the libgit2 library ##' ##' Version of the libgit2 library that the bundled source code is ##' based on ##' @return A list with major, minor and rev ##' @keywords methods ##' @export ##' @useDynLib git2r git2r_libgit2_version ##' @examples ##' libgit2_version() libgit2_version <- function() { .Call(git2r_libgit2_version) } ##' Set the SSL certificate-authority locations ##' ##' @note Either parameter may be 'NULL', but not both. ##' @param filename Location of a file containing several certificates ##' concatenated together. Default NULL. ##' @param path Location of a directory holding several certificates, ##' one per file. Default NULL. ##' @return invisible(NULL) ##' @keywords methods ##' @export ##' @useDynLib git2r git2r_ssl_cert_locations ssl_cert_locations <- function(filename = NULL, path = NULL) { .Call(git2r_ssl_cert_locations, filename, path) invisible(NULL) } git2r/R/refspec.R0000644000176200001440000000473314704117375013274 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Create push refspec from arguments ##' ##' @param repo a \code{git_repository} object. ##' @param name The remote's name. Default is NULL. ##' @param refspec The refspec to be pushed. Default is NULL. ##' @param opts List with push options. Default is NULL. ##' @return List with remote (character vector) and refspec (character ##' vector). ##' @useDynLib git2r git2r_config_get_string ##' @noRd get_refspec <- function(repo = NULL, remote = NULL, spec = NULL, opts = NULL) { stopifnot(inherits(repo, "git_repository")) if (is_detached(repo)) stop("You are not currently on a branch.") ## Options: if (!is.null(opts)) { stopifnot(is.list(opts)) } else { opts <- list() } ## Remote: ## From: http://git-scm.com/docs/git-push ## When the command line does not specify where to push with the ## argument, branch.*.remote configuration for the ## current branch is consulted to determine where to push. If the ## configuration is missing, it defaults to origin. if (!is.null(remote)) { stopifnot(is.character(remote), identical(length(remote), 1L)) remote <- sub("^[[:space:]]*", "", sub("[[:space:]]*$", "", remote)) if (identical(nchar(remote), 0L)) remote <- NULL } if (is.null(remote)) { remote <- .Call(git2r_config_get_string, repo, paste0("branch.", repository_head(repo)$name, ".remote")) if (is.null(remote)) remote <- "origin" } ## Refspec: stopifnot(is.character(spec)) if (isTRUE(opts$force)) spec <- paste0("+", spec) list(remote = remote, refspec = spec) } git2r/R/contributions.R0000644000176200001440000001043514704115344014535 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Contributions ##' ##' See contributions to a Git repo ##' @template repo-param ##' @param breaks Default is \code{month}. Change to year, quarter, ##' week or day as necessary. ##' @param by Contributions by "commits" or "author". Default is "commits". ##' @return A \code{data.frame} with contributions. ##' @export ##' @useDynLib git2r git2r_revwalk_contributions ##' @examples ##' \dontrun{ ##' ## Create directories and initialize repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo_1 <- tempfile(pattern="git2r-") ##' path_repo_2 <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' dir.create(path_repo_1) ##' dir.create(path_repo_2) ##' repo_bare <- init(path_bare, bare = TRUE) ##' ##' ## Clone to repo 1 and config user ##' repo_1 <- clone(path_bare, path_repo_1) ##' config(repo_1, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Add changes to repo 1 and push to bare ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path_repo_1, "test.txt")) ##' add(repo_1, "test.txt") ##' commit(repo_1, "First commit message") ##' ##' ## Add more changes to repo 1 ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path_repo_1, "test.txt")) ##' add(repo_1, "test.txt") ##' commit(repo_1, "Second commit message") ##' ##' ## Push to bare ##' push(repo_1, "origin", "refs/heads/master") ##' ##' ## Clone to repo 2 ##' repo_2 <- clone(path_bare, path_repo_2) ##' config(repo_2, user.name = "Bob", user.email = "bob@@example.org") ##' ##' ## Add changes to repo 2 ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", ##' "minim veniam, quis nostrud exercitation ullamco laboris nisi ut") ##' writeLines(lines, file.path(path_repo_2, "test.txt")) ##' add(repo_2, "test.txt") ##' commit(repo_2, "Third commit message") ##' ##' ## Push to bare ##' push(repo_2, "origin", "refs/heads/master") ##' ##' ## Pull changes to repo 1 ##' pull(repo_1) ##' ##' ## View contributions by day ##' contributions(repo_1) ##' ##' ## View contributions by author and day ##' contributions(repo_1, by = "author") ##' } contributions <- function(repo = ".", breaks = c("month", "year", "quarter", "week", "day"), by = c("commits", "author")) { breaks <- match.arg(breaks) by <- match.arg(by) ctbs <- .Call(git2r_revwalk_contributions, lookup_repository(repo), TRUE, TRUE, FALSE) ctbs$when <- as.POSIXct(ctbs$when, origin = "1970-01-01", tz = "GMT") ctbs$when <- as.POSIXct(cut(ctbs$when, breaks = breaks)) if (identical(by, "commits")) { ctbs <- as.data.frame(table(ctbs$when)) names(ctbs) <- c("when", "n") ctbs$when <- as.Date(ctbs$when) } else { ## Create an index and tabulate ctbs$index <- paste0(ctbs$when, ctbs$author, ctbs$email) count <- as.data.frame(table(ctbs$index), stringsAsFactors = FALSE) names(count) <- c("index", "n") ## Match counts and clean result ctbs <- as.data.frame(ctbs) ctbs$n <- count$n[match(ctbs$index, count$index)] ctbs <- unique(ctbs[, c("when", "author", "n")]) ctbs$when <- as.Date(substr(as.character(ctbs$when), 1, 10)) ctbs <- ctbs[order(ctbs$when, ctbs$author), ] row.names(ctbs) <- NULL } ctbs } git2r/R/punch_card.R0000644000176200001440000000614513526222552013745 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2018 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Punch card ##' ##' @template repo-param ##' @param main Default title for the plot is "Punch card on repo:" ##' and repository workdir basename. Supply a new title if you ##' desire one. ##' @param ... Additional arguments affecting the plot ##' @return invisible NULL ##' @importFrom graphics axis ##' @importFrom graphics par ##' @importFrom graphics plot.new ##' @importFrom graphics plot.window ##' @importFrom graphics symbols ##' @importFrom graphics title ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- clone("https://github.com/ropensci/git2r.git", path) ##' ##' ## Plot ##' punch_card(repo) ##' } punch_card <- function(repo = ".", main = NULL, ...) { savepar <- graphics::par(las = 1, mar = c(2.2, 6, 2, 0)) on.exit(par(savepar)) wd <- c("Saturday", "Friday", "Thursday", "Wednesday", "Tuesday", "Monday", "Sunday") ## Extract information from repository repo <- lookup_repository(repo) df <- as.data.frame(repo) df$when <- as.POSIXlt(df$when) df$hour <- df$when$hour df$weekday <- df$when$wday ## Create a key and tabulate df$key <- paste0(df$weekday, "-", df$hour) df <- as.data.frame(table(df$key), stringsAsFactors = FALSE) names(df) <- c("key", "Commits") ## Convert key to Weekday and Hour df$Weekday <- sapply(strsplit(df$key, "-"), "[", 1) df$Weekday <- factor(df$Weekday, levels = c(6, 5, 4, 3, 2, 1, 0), labels = wd) df$Hour <- as.integer(sapply(strsplit(df$key, "-"), "[", 2)) df$key <- paste0(df$Weekday, "-", df$Hour) ## Scale df$Commits <- sqrt((df$Commits / max(df$Commits)) / pi) plot.new() plot.window(xlim = c(0, 23), ylim = c(0.8, 7.2)) symbols(df$ Hour, df$Weekday, circles = df$Commits, xaxt = "n", yaxt = "n", inches = FALSE, fg = "white", bg = "black", add = TRUE, ...) h <- 0:23 h <- paste0(ifelse(h > 9, as.character(h), paste0("0", as.character(h))), ":00") axis(1, at = 0:23, labels = h) axis(2, at = 1:7, labels = wd) if (is.null(main)) { if (is_bare(repo)) { main <- "Punch card" } else { main <- sprintf("Punch card on repository: %s", basename(workdir(repo))) } } title(main) invisible(NULL) } git2r/R/push.R0000644000176200001440000001177014704116555012622 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. get_upstream_name <- function(object) { upstream <- branch_get_upstream(object) if (is.null(upstream)) { stop("The branch '", object$name, "' that you are ", "trying to push does not track an upstream branch.") } branch_remote_name(upstream) } ##' Push ##' ##' @param object path to repository, or a \code{git_repository} or ##' \code{git_branch}. ##' @param name The remote's name. Default is NULL. ##' @param refspec The refspec to be pushed. Default is NULL. ##' @param force Force your local revision to the remote repo. Use it ##' with care. Default is FALSE. ##' @param credentials The credentials for remote repository ##' access. Default is NULL. To use and query an ssh-agent for the ##' ssh key credentials, let this parameter be NULL (the default). ##' @param set_upstream Set the current local branch to track the ##' remote branch. Default is FALSE. ##' @return invisible(NULL) ##' @seealso \code{\link{cred_user_pass}}, \code{\link{cred_ssh_key}} ##' @export ##' @useDynLib git2r git2r_branch_canonical_name ##' @useDynLib git2r git2r_branch_upstream_canonical_name ##' @useDynLib git2r git2r_push ##' @examples ##' \dontrun{ ##' ## Initialize two temporary repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' dir.create(path_repo) ##' repo_bare <- init(path_bare, bare = TRUE) ##' ##' ## Clone the bare repository. This creates remote-tracking ##' ## branches for each branch in the cloned repository. ##' repo <- clone(path_bare, path_repo) ##' ##' ## Config user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path_repo, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Push commits from repository to bare repository ##' push(repo, "origin", "refs/heads/master") ##' ##' ## Now, unset the remote-tracking branch to NULL to demonstrate ##' ## the 'set_upstream' argument. Then push with 'set_upstream = TRUE' ##' ## to add the upstream tracking branch to branch 'master' again. ##' branch_get_upstream(repository_head(repo)) ##' branch_set_upstream(repository_head(repo), NULL) ##' branch_get_upstream(repository_head(repo)) ##' push(repo, "origin", "refs/heads/master", set_upstream = TRUE) ##' branch_get_upstream(repository_head(repo)) ##' ##' ## Change file and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path_repo, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "Second commit message") ##' ##' ## Push commits from repository to bare repository ##' push(repo) ##' ##' ## List commits in repository and bare repository ##' commits(repo) ##' commits(repo_bare) ##' } push <- function(object = ".", name = NULL, refspec = NULL, force = FALSE, credentials = NULL, set_upstream = FALSE) { if (is_branch(object)) { name <- get_upstream_name(object) src <- .Call(git2r_branch_canonical_name, object) dst <- .Call(git2r_branch_upstream_canonical_name, object) refspec <- paste0(src, ":", dst) object <- object$repo } else { object <- lookup_repository(object) } if (all(is.null(name), is.null(refspec))) { b <- repository_head(object) name <- get_upstream_name(b) src <- .Call(git2r_branch_canonical_name, b) dst <- .Call(git2r_branch_upstream_canonical_name, b) refspec <- paste0(src, ":", dst) if (isTRUE(force)) refspec <- paste0("+", refspec) } else { opts <- list(force = force) tmp <- get_refspec(object, name, refspec, opts) name <- tmp$remote refspec <- tmp$refspec } .Call(git2r_push, object, name, refspec, credentials) if (isTRUE(set_upstream)) { b <- repository_head(object) if (is_local(b)) branch_set_upstream(b, paste0(name, "/", b$name)) } invisible(NULL) } git2r/R/tree.R0000644000176200001440000002436714704742463012613 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Coerce entries in a git_tree to a \code{data.frame} ##' ##' The entries in a tree are coerced to a \code{data.frame} ##' ##' ##' The \code{data.frame} have the following columns: ##' \describe{ ##' ##' \item{filemode}{ ##' The UNIX file attributes of a tree entry ##' } ##' ##' \item{type}{ ##' String representation of the tree entry type ##' } ##' ##' \item{sha}{ ##' The sha of a tree entry ##' } ##' ##' \item{name}{ ##' The filename of a tree entry ##' } ##' ##' } ##' @param x The tree \code{object} ##' @param ... Additional arguments. Not used. ##' @return \code{data.frame} ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' dir.create(file.path(path, "subfolder")) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create three files and commit ##' writeLines("First file", file.path(path, "example-1.txt")) ##' writeLines("Second file", file.path(path, "subfolder/example-2.txt")) ##' writeLines("Third file", file.path(path, "example-3.txt")) ##' add(repo, c("example-1.txt", "subfolder/example-2.txt", "example-3.txt")) ##' commit(repo, "Commit message") ##' ##' ## Display tree ##' tree(last_commit(repo)) ##' ##' ## Coerce tree to a data.frame ##' df <- as.data.frame(tree(last_commit(repo))) ##' df ##' } as.data.frame.git_tree <- function(x, ...) { data.frame(mode = sprintf("%06o", x$filemode), type = x$type, sha = x$id, name = x$name, stringsAsFactors = FALSE) } ##' @export base::as.data.frame ##' Coerce entries in a git_tree to a list of entry objects ##' ##' @param x The tree \code{object} ##' @param ... Unused ##' @return list of entry objects ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' dir.create(file.path(path, "subfolder")) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create three files and commit ##' writeLines("First file", file.path(path, "example-1.txt")) ##' writeLines("Second file", file.path(path, "subfolder/example-2.txt")) ##' writeLines("Third file", file.path(path, "example-3.txt")) ##' add(repo, c("example-1.txt", "subfolder/example-2.txt", "example-3.txt")) ##' commit(repo, "Commit message") ##' ##' ## Inspect size of each blob in tree ##' invisible(lapply(as(tree(last_commit(repo)), "list"), ##' function(obj) { ##' if (is_blob(obj)) ##' summary(obj) ##' NULL ##' })) ##' } as.list.git_tree <- function(x, ...) { lapply(x$id, function(sha) lookup(x$repo, sha)) } ##' Tree ##' ##' Get the tree pointed to by a commit or stash. ##' @param object the \code{commit} or \code{stash} object ##' @return A S3 class git_tree object ##' @export ##' @useDynLib git2r git2r_commit_tree ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a first user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' tree(last_commit(repo)) ##' } tree <- function(object = NULL) { .Call(git2r_commit_tree, object) } ##' @export print.git_tree <- function(x, ...) { cat(sprintf("tree: %s\n\n", x$sha)) print(as.data.frame(x)) invisible(x) } ##' Summary of tree ##' ##' @param object The tree \code{object} ##' @param ... Additional arguments affecting the summary produced. ##' @return None (invisible 'NULL'). ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' summary(tree(last_commit(repo))) ##' } summary.git_tree <- function(object, ...) { print(as.data.frame(object)) } ##' Extract object from tree ##' ##' Lookup a tree entry by its position in the tree ##' @param x The tree \code{object} ##' @param i The index (integer or logical) of the tree object to ##' extract. If negative values, all elements except those indicated ##' are selected. A character vector to match against the names of ##' objects to extract. ##' @return Git object ##' @export ##' @examples ##' \dontrun{ ##' ##' Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' dir.create(file.path(path, "subfolder")) ##' repo <- init(path) ##' ##' ##' Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ##' Create three files and commit ##' writeLines("First file", file.path(path, "example-1.txt")) ##' writeLines("Second file", file.path(path, "subfolder/example-2.txt")) ##' writeLines("Third file", file.path(path, "example-3.txt")) ##' add(repo, c("example-1.txt", "subfolder/example-2.txt", "example-3.txt")) ##' new_commit <- commit(repo, "Commit message") ##' ##' ##' Pick a tree in the repository ##' tree_object <- tree(new_commit) ##' ##' ##' Display tree ##' tree_object ##' ##' ##' Select item by name ##' tree_object["example-1.txt"] ##' ##' ##' Select first item in tree ##' tree_object[1] ##' ##' ##' Select first three items in tree ##' tree_object[1:3] ##' ##' ##' Select all blobs in tree ##' tree_object[vapply(as(tree_object, 'list'), is_blob, logical(1))] ##' } "[.git_tree" <- function(x, i) { if (is.logical(i)) return(x[seq_along(x)[i]]) if (is.character(i)) return(x[which(x$name %in% i)]) if (!is.numeric(i)) stop("Invalid index") i <- seq_len(length(x))[as.integer(i)] ret <- lapply(i, function(j) lookup(x$repo, x$id[j])) if (identical(length(ret), 1L)) ret <- ret[[1]] ret } ##' Number of entries in tree ##' ##' @param x The tree \code{object} ##' @return a non-negative integer or double (which will be rounded ##' down) ##' @export length.git_tree <- function(x) { length(x$id) } ##' Check if object is S3 class git_tree ##' ##' @param object Check if object is S3 class git_tree ##' @return TRUE if object is S3 class git_tree, else FALSE ##' @keywords methods ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Commit a text file ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "First commit message") ##' tree_1 <- tree(commit_1) ##' ##' ## Check if tree ##' is_tree(commit_1) ##' is_tree(tree_1) ##' } is_tree <- function(object) { inherits(object, "git_tree") } ##' List the contents of a tree object ##' ##' Traverse the entries in a tree and its subtrees. Akin to the 'git ##' ls-tree' command. ##' @param tree default (\code{NULL}) is the tree of the last commit ##' in \code{repo}. Can also be a \code{git_tree} object or a ##' character that identifies a tree in the repository (see ##' \sQuote{Examples}). ##' @param repo never used if \code{tree} is a \code{git_tree} ##' object. A \code{git_repository} object, or a path (default = ##' '.') to a repository. ##' @param recursive default is to recurse into sub-trees. ##' @return A data.frame with the following columns: \describe{ ##' \item{mode}{UNIX file attribute of the tree entry} ##' \item{type}{type of object} \item{sha}{sha of the object} ##' \item{path}{path relative to the root tree} ##' \item{name}{filename of the tree entry} \item{len}{object size ##' of blob (file) entries. NA for other objects.} } ##' @export ##' @useDynLib git2r git2r_tree_walk ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' dir.create(file.path(path, "subfolder")) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create three files and commit ##' writeLines("First file", file.path(path, "example-1.txt")) ##' writeLines("Second file", file.path(path, "subfolder/example-2.txt")) ##' writeLines("Third file", file.path(path, "example-3.txt")) ##' add(repo, c("example-1.txt", "subfolder/example-2.txt", "example-3.txt")) ##' commit(repo, "Commit message") ##' ##' ## Traverse tree entries and its subtrees. ##' ## Various approaches that give identical result. ##' ls_tree(tree = tree(last_commit(path))) ##' ls_tree(tree = tree(last_commit(repo))) ##' ls_tree(repo = path) ##' ls_tree(repo = repo) ##' ##' ## Skip content in subfolder ##' ls_tree(repo = repo, recursive = FALSE) ##' ##' ## Start in subfolder ##' ls_tree(tree = "HEAD:subfolder", repo = repo) ##' } ls_tree <- function(tree = NULL, repo = ".", recursive = TRUE) { if (is.null(tree)) { tree <- tree(last_commit(lookup_repository(repo))) } else if (is.character(tree)) { tree <- revparse_single(repo = lookup_repository(repo), revision = tree) if (!is_tree(tree)) tree <- tree(tree) } data.frame(.Call(git2r_tree_walk, tree, recursive), stringsAsFactors = FALSE) } git2r/R/when.R0000644000176200001440000000502313565057155012602 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2019 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' When ##' ##' Help method to extract the time as a character string from a ##' git_commit, git_signature, git_tag and git_time object. ##' @param object the \code{object} to extract the time slot from. ##' @inheritParams base::as.POSIXct ##' @inheritParams base::strptime ##' @return A \code{character} vector of length one. ##' @seealso \code{\link{git_time}} ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a first user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Create tag ##' tag(repo, "Tagname", "Tag message") ##' ##' when(commits(repo)[[1]]) ##' when(tags(repo)[[1]]) ##' when(tags(repo)[[1]], tz = Sys.timezone()) ##' } when <- function(object, tz = "GMT", origin = "1970-01-01", usetz = TRUE) { if (inherits(object, "git_commit")) return(as.character(object$author$when, tz = tz, origin = origin, usetz = usetz)) if (inherits(object, "git_signature")) return(as.character(object$when, tz = tz, origin = origin, usetz = usetz)) if (inherits(object, "git_stash")) return(as.character(object$stasher$when, tz = tz, origin = origin, usetz = usetz)) if (inherits(object, "git_tag")) return(as.character(object$tagger$when, tz = tz, origin = origin, usetz = usetz)) if (inherits(object, "git_time")) return(as.character(object, tz = tz, origin = origin, usetz = usetz)) stop("Invalid 'object'") } git2r/R/reference.R0000644000176200001440000000451014704117276013574 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Get all references that can be found in a repository. ##' @template repo-param ##' @return Character vector with references ##' @export ##' @useDynLib git2r git2r_reference_list ##' @examples ##' \dontrun{ ##' ## Initialize two temporary repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo <- tempfile(pattern="git2r-") ##' dir.create(path_bare) ##' dir.create(path_repo) ##' repo_bare <- init(path_bare, bare = TRUE) ##' repo <- clone(path_bare, path_repo) ##' ##' ## Config user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path_repo, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Push commits from repository to bare repository ##' ## Adds an upstream tracking branch to branch 'master' ##' push(repo, "origin", "refs/heads/master") ##' ##' ## Add tag to HEAD ##' tag(repo, "v1.0", "First version") ##' ##' ## Create a note ##' note_create(commits(repo)[[1]], "My note") ##' ##' ## List all references in repository ##' references(repo) ##' } ##' references <- function(repo = ".") { .Call(git2r_reference_list, lookup_repository(repo)) } ##' @export format.git_reference <- function(x, ...) { if (identical(x$type, 1L)) return(sprintf("[%s] %s", substr(x$sha, 1, 6), x$shorthand)) sprintf("%s => %s", x$name, x$target) } ##' @export print.git_reference <- function(x, ...) { cat(format(x, ...), "\n", sep = "") invisible(x) } git2r/R/status.R0000644000176200001440000000712614704114143013155 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Status ##' ##' Display state of the repository working directory and the staging ##' area. ##' @template repo-param ##' @param staged Include staged files. Default TRUE. ##' @param unstaged Include unstaged files. Default TRUE. ##' @param untracked Include untracked files and directories. Default ##' TRUE. ##' @param ignored Include ignored files. Default FALSE. ##' @param all_untracked Shows individual files in untracked ##' directories if \code{untracked} is \code{TRUE}. ##' @return \code{git_status} with repository status ##' @export ##' @useDynLib git2r git2r_status_list ##' @examples ##' \dontrun{ ##' ## Initialize a repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Config user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file ##' writeLines("Hello world!", file.path(path, "test.txt")) ##' ##' ## Check status; untracked file ##' status(repo) ##' ##' ## Add file ##' add(repo, "test.txt") ##' ##' ## Check status; staged file ##' status(repo) ##' ##' ## Commit ##' commit(repo, "First commit message") ##' ##' ## Check status; clean ##' status(repo) ##' ##' ## Change the file ##' writeLines(c("Hello again!", "Here is a second line", "And a third"), ##' file.path(path, "test.txt")) ##' ##' ## Check status; unstaged file ##' status(repo) ##' ##' ## Add file and commit ##' add(repo, "test.txt") ##' commit(repo, "Second commit message") ##' ##' ## Check status; clean ##' status(repo) ##'} status <- function(repo = ".", staged = TRUE, unstaged = TRUE, untracked = TRUE, ignored = FALSE, all_untracked = FALSE) { structure(.Call(git2r_status_list, lookup_repository(repo), staged, unstaged, untracked, all_untracked, ignored), class = "git_status") } ##' @export print.git_status <- function(x, ...) { display_status <- function(title, section) { cat(sprintf("%s:\n", title)) for (i in seq_len(length(section))) { label <- names(section)[i] label <- paste0(toupper(substr(label, 1, 1)), substr(label, 2, nchar(label))) cat(sprintf("\t%-12s%s\n", paste0(label, ":"), section[[i]])) } invisible(NULL) } if (max(sapply(x, length)) == 0L) cat("working directory clean\n") if (length(x$ignored)) { display_status("Ignored files", x$ignored) cat("\n") } if (length(x$untracked)) { display_status("Untracked files", x$untracked) cat("\n") } if (length(x$unstaged)) { display_status("Unstaged changes", x$unstaged) cat("\n") } if (length(x$staged)) { display_status("Staged changes", x$staged) cat("\n") } invisible(x) } git2r/R/config.R0000644000176200001440000001504514704027466013111 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Config ##' ##' Config file management. To display the configuration variables, ##' call method \code{config} without the \code{user.name}, ##' \code{user.email} or \code{...} options. ##' ##' There are two ways git2r can find the local repository when ##' writing local options (1) Use the \code{repo} argument. (2) If the ##' \code{repo} argument is \code{NULL} but the current working ##' directory is inside the local repository, then \code{git2r} uses ##' that repository. ##' @param repo The \code{repository}. Default is NULL. ##' @param global Write option(s) to global configuration ##' file. Default is FALSE. ##' @param user.name The user name. Use NULL to delete the entry ##' @param user.email The e-mail address. Use NULL to delete the entry ##' @param ... Additional options to write or delete from the ##' configuration. ##' @return S3 class \code{git_config}. When writing options, the ##' configuration is returned invisible. ##' @export ##' @useDynLib git2r git2r_config_get ##' @useDynLib git2r git2r_config_set ##' @examples \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern = "git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Set user name and email. ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Display configuration ##' config(repo) ##' ##' ## Delete user email. ##' config(repo, user.email = NULL) ##' ##' ## Display configuration ##' config(repo) ##' } config <- function(repo = NULL, global = FALSE, user.name, user.email, ...) { if (is.null(repo)) { repo <- discover_repository(getwd()) if (!is.null(repo)) repo <- repository(repo) } ## Check that 'global' is either TRUE or FALSE stopifnot(any(identical(global, TRUE), identical(global, FALSE))) variables <- list(...) if (!missing(user.name)) variables <- c(variables, list(user.name = user.name)) if (!missing(user.email)) variables <- c(variables, list(user.email = user.email)) if (length(variables)) { for (i in seq_len(length(variables))) { if (!is.null(variables[[i]])) { if (!is.character(variables[[i]])) { stop("'", names(variables)[i], "' must be a character vector") } } } if (isTRUE(global)) { repo <- NULL if (.Platform$OS.type == "windows") { ## Ensure that git2r writes the config file to the ## root of the user's home directory by first creating ## an empty file. Otherwise it may be written to the ## user's Documents/ directory. Only create the empty ## file if the user has specified configuration ## options to set and no global config file exists. if (is.na(git_config_files()[["path"]][3])) { if (length(variables) > 0) { file.create(file.path(home_dir(), ".gitconfig")) } } } } else if (is.null(repo)) { stop("Unable to locate local repository") } .Call(git2r_config_set, repo, variables) } cfg <- .Call(git2r_config_get, repo) ## Sort the variables within levels by name cfg <- structure(lapply(cfg, function(x) x[order(names(x))]), class = "git_config") if (length(variables)) { invisible(cfg) } else { return(cfg) } } ##' @export print.git_config <- function(x, ...) { lapply(names(x), function(level) { cat(sprintf("%s:\n", level)) lapply(names(x[[level]]), function(entry) { cat(sprintf(" %s=%s\n", entry, x[[level]][[entry]][1])) }) }) invisible(x) } ##' Locate the path to configuration files ##' ##' Potential configuration files: ##' \describe{ ##' \item{system}{ ##' Locate the path to the system configuration file. If ##' '/etc/gitconfig' doesn't exist, it will look for ##' '\%PROGRAMFILES\%'. ##' } ##' \item{xdg}{ ##' Locate the path to the global xdg compatible configuration ##' file. The xdg compatible configuration file is usually located ##' in '$HOME/.config/git/config'. This method will try to guess ##' the full path to that file, if the file exists. ##' } ##' \item{global}{ ##' The user or global configuration file is usually located in ##' '$HOME/.gitconfig'. This method will try to guess the full ##' path to that file, if the file exists. ##' } ##' \item{local}{ ##' Locate the path to the repository specific configuration file, ##' if the file exists. ##' } ##' } ##' @template repo-param ##' @return a \code{data.frame} with one row per potential ##' configuration file where \code{NA} means not found. ##' @export ##' @useDynLib git2r git2r_config_find_file git_config_files <- function(repo = ".") { ## Lookup repository if (inherits(repo, "git_repository")) { repo <- repo$path } else if (is.null(repo)) { repo <- discover_repository(getwd()) } else if (is.character(repo) && (length(repo) == 1) && !is.na(repo) && isTRUE(file.info(repo)$isdir)) { repo <- discover_repository(repo) } else { repo <- NULL } ## Find local configuration file if (is.null(repo)) { path <- NA_character_ } else { path <- file.path(normalizePath(repo), "config") if (!isTRUE(!file.info(path)$isdir)) path <- NA_character_ } data.frame(file = c("system", "xdg", "global", "local"), path = c(.Call(git2r_config_find_file, "system"), .Call(git2r_config_find_file, "xdg"), .Call(git2r_config_find_file, "global"), path), stringsAsFactors = FALSE) } git2r/R/commit.R0000644000176200001440000005051514704024755013133 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Ahead Behind ##' ##' Count the number of unique commits between two commit objects. ##' @param local a git_commit object. Can also be a tag or a branch, ##' and in that case the commit will be the target of the tag or ##' branch. ##' @param upstream a git_commit object. Can also be a tag or a ##' branch, and in that case the commit will be the target of the ##' tag or branch. ##' @return An integer vector of length 2 with number of commits that ##' the upstream commit is ahead and behind the local commit ##' @export ##' @useDynLib git2r git2r_graph_ahead_behind ##' @examples \dontrun{ ##' ## Create a directory in tempdir ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' ##' ## Initialize a repository ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "test.txt")) ##' add(repo, "test.txt") ##' commit_1 <- commit(repo, "Commit message 1") ##' tag_1 <- tag(repo, "Tagname1", "Tag message 1") ##' ##' # Change file and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path, "test.txt")) ##' add(repo, "test.txt") ##' commit_2 <- commit(repo, "Commit message 2") ##' tag_2 <- tag(repo, "Tagname2", "Tag message 2") ##' ##' ahead_behind(commit_1, commit_2) ##' ahead_behind(tag_1, tag_2) ##' } ahead_behind <- function(local = NULL, upstream = NULL) { .Call(git2r_graph_ahead_behind, lookup_commit(local), lookup_commit(upstream)) } ##' Add sessionInfo to message ##' ##' @param message The message. ##' @return message with appended sessionInfo ##' @importFrom utils capture.output ##' @importFrom utils sessionInfo ##' @noRd add_session_info <- function(message) { paste0(message, "\n\nsessionInfo:\n", paste0(utils::capture.output(utils::sessionInfo()), collapse = "\n")) } ##' Commit ##' ##' @template repo-param ##' @param message The commit message. ##' @param all Stage modified and deleted files. Files not added to ##' Git are not affected. ##' @param session Add sessionInfo to commit message. Default is ##' FALSE. ##' @param author Signature with author and author time of commit. ##' @param committer Signature with committer and commit time of ##' commit. ##' @return A list of class \code{git_commit} with entries: ##' \describe{ ##' \item{sha}{ ##' The 40 character hexadecimal string of the SHA-1 ##' } ##' \item{author}{ ##' An author signature ##' } ##' \item{committer}{ ##' The committer signature ##' } ##' \item{summary}{ ##' The short "summary" of a git commit message, comprising the first ##' paragraph of the message with whitespace trimmed and squashed. ##' } ##' \item{message}{ ##' The message of a commit ##' } ##' \item{repo}{ ##' The \code{git_repository} object that contains the commit ##' } ##' } ##' @export ##' @useDynLib git2r git2r_commit ##' @useDynLib git2r git2r_index_remove_bypath ##' @examples ##' \dontrun{ ##' ## Initialize a repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Config user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' } commit <- function(repo = ".", message = NULL, all = FALSE, session = FALSE, author = NULL, committer = NULL) { repo <- lookup_repository(repo) if (is.null(author)) author <- default_signature(repo) if (is.null(committer)) committer <- default_signature(repo) stopifnot(is.character(message), identical(length(message), 1L)) if (!nchar(message[1])) stop("Aborting commit due to empty commit message.") if (isTRUE(all)) { s <- status(repo, unstaged = TRUE, staged = FALSE, untracked = FALSE, ignored = FALSE) ## Convert list of lists to character vector unstaged <- unlist(s$unstaged) for (i in seq_along(unstaged)) { if (names(unstaged)[i] == "modified") { ## Stage modified files add(repo, unstaged[i]) } else if (names(unstaged)[i] == "deleted") { ## Stage deleted files .Call(git2r_index_remove_bypath, repo, unstaged[i]) } } } if (isTRUE(session)) message <- add_session_info(message) .Call(git2r_commit, repo, message, author, committer) } ##' Check limit in number of commits ##' @noRd get_upper_limit_of_commits <- function(n) { if (is.null(n)) { n <- -1L } else if (is.numeric(n)) { if (!identical(length(n), 1L)) stop("'n' must be integer") if (abs(n - round(n)) >= .Machine$double.eps^0.5) stop("'n' must be integer") n <- as.integer(n) } else { stop("'n' must be integer") } n } shallow_commits <- function(repo, sha, n) { ## List to hold result result <- list() ## Get latest commit x <- lookup(repo, sha) ## Repeat until no more parent commits repeat { if (n == 0) { break } else if (n > 0) { n <- n - 1 } if (is.null(x)) break result[[length(result) + 1]] <- x ## Get parent to commit x <- tryCatch(parents(x)[[1]], error = function(e) NULL) } result } ##' Commits ##' ##' @template repo-param ##' @param topological Sort the commits in topological order (parents ##' before children); can be combined with time sorting. Default ##' is TRUE. ##' @param time Sort the commits by commit time; Can be combined with ##' topological sorting. Default is TRUE. ##' @param reverse Sort the commits in reverse order; can be combined ##' with topological and/or time sorting. Default is FALSE. ##' @param n The upper limit of the number of commits to output. The ##' default is NULL for unlimited number of commits. ##' @param ref The name of a reference to list commits from e.g. a tag ##' or a branch. The default is NULL for the current branch. ##' @param path The path to a file. If not NULL, only commits modifying ##' this file will be returned. Note that modifying commits that ##' occurred before the file was given its present name are not ##' returned; that is, the output of \code{git log} with ##' \code{--no-follow} is reproduced. ##' @return list of commits in repository ##' @export ##' @useDynLib git2r git2r_reference_dwim ##' @useDynLib git2r git2r_revwalk_list2 ##' @useDynLib git2r git2r_revwalk_list ##' @examples ##' \dontrun{ ##' ## Initialize a repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Config user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Change file and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "Second commit message") ##' ##' ## Create a tag ##' tag(repo, "Tagname", "Tag message") ##' ##' ## Change file again and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", ##' "minim veniam, quis nostrud exercitation ullamco laboris nisi ut") ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "Third commit message") ##' ##' ## Create a new file containing R code, and commit. ##' writeLines(c("x <- seq(1,100)", ##' "print(mean(x))"), ##' file.path(path, "mean.R")) ##' add(repo, "mean.R") ##' commit(repo, "Fourth commit message") ##' ##' ## List the commits in the repository ##' commits(repo) ##' ##' ## List the commits starting from the tag ##' commits(repo, ref = "Tagname") ##' ##' ## List the commits modifying example.txt and mean.R. ##' commits(repo, path = "example.txt") ##' commits(repo, path = "mean.R") ##' ##' ## Create and checkout 'dev' branch in the repo ##' checkout(repo, "dev", create = TRUE) ##' ##' ## Add changes to the 'dev' branch ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "Commit message in dev branch") ##' ##' ## Checkout the 'master' branch again and list the commits ##' ## starting from the 'dev' branch. ##' checkout(repo, "master") ##' commits(repo, ref = "dev") ##' } commits <- function(repo = ".", topological = TRUE, time = TRUE, reverse = FALSE, n = NULL, ref = NULL, path = NULL) { ## Check limit in number of commits n <- get_upper_limit_of_commits(n) if (!is.null(path)) { if (!(is.character(path) && length(path) == 1)) { stop("path must be a single file") } } repo <- lookup_repository(repo) if (is_empty(repo)) return(list()) if (is.null(ref)) { sha <- sha(repository_head(repo)) } else { sha <- sha(lookup_commit(.Call(git2r_reference_dwim, repo, ref))) } if (is_shallow(repo)) { ## FIXME: Remove this if-statement when libgit2 supports ## shallow clones, see #219. Note: This workaround does not ## use the 'topological', 'time' and 'reverse' flags. return(shallow_commits(repo, sha, n)) } if (!is.null(path)) { repo_wd <- normalizePath(workdir(repo), winslash = "/") path <- sanitize_path(path, repo_wd) path_revwalk <- .Call(git2r_revwalk_list2, repo, sha, topological, time, reverse, n, path) return(path_revwalk[!vapply(path_revwalk, is.null, logical(1))]) } .Call(git2r_revwalk_list, repo, sha, topological, time, reverse, n) } ##' Last commit ##' ##' Get last commit in the current branch. ##' @template repo-param ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Config user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Write to a file and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Get last commit ##' last_commit(repo) ##' last_commit(path) ##' ##' ## Coerce the last commit to a data.frame ##' as.data.frame(last_commit(path), "data.frame") ##' ##' ## Summary of last commit in repository ##' summary(last_commit(repo)) ##' } last_commit <- function(repo = ".") { commits(lookup_repository(repo), n = 1)[[1]] } ##' Descendant ##' ##' Determine if a commit is the descendant of another commit ##' @param commit a git_commit object. Can also be a tag or a branch, ##' and in that case the commit will be the target of the tag or ##' branch. ##' @param ancestor a git_commit object to check if ancestor to ##' \code{commit}. Can also be a tag or a branch, and in that case ##' the commit will be the target of the tag or branch. ##' @return TRUE if \code{commit} is descendant of \code{ancestor}, ##' else FALSE ##' @export ##' @useDynLib git2r git2r_graph_descendant_of ##' @examples ##' \dontrun{ ##' ## Create a directory in tempdir ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' ##' ## Initialize a repository ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" ##' writeLines(lines, file.path(path, "test.txt")) ##' add(repo, "test.txt") ##' commit_1 <- commit(repo, "Commit message 1") ##' tag_1 <- tag(repo, "Tagname1", "Tag message 1") ##' ##' # Change file and commit ##' lines <- c( ##' "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", ##' "eiusmod tempor incididunt ut labore et dolore magna aliqua.") ##' writeLines(lines, file.path(path, "test.txt")) ##' add(repo, "test.txt") ##' commit_2 <- commit(repo, "Commit message 2") ##' tag_2 <- tag(repo, "Tagname2", "Tag message 2") ##' ##' descendant_of(commit_1, commit_2) ##' descendant_of(commit_2, commit_1) ##' descendant_of(tag_1, tag_2) ##' descendant_of(tag_2, tag_1) ##' } descendant_of <- function(commit = NULL, ancestor = NULL) { .Call(git2r_graph_descendant_of, lookup_commit(commit), lookup_commit(ancestor)) } ##' Check if object is a git_commit object ##' ##' @param object Check if object is a git_commit object ##' @return TRUE if object is a git_commit, else FALSE ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Commit a text file ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "First commit message") ##' ##' ## Check if commit ##' is_commit(commit_1) ##' } is_commit <- function(object) { inherits(object, "git_commit") } ##' Is merge ##' ##' Determine if a commit is a merge commit, i.e. has more than one ##' parent. ##' @param commit a git_commit object. ##' @return TRUE if commit has more than one parent, else FALSE ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' writeLines(c("First line in file 1.", "Second line in file 1."), ##' file.path(path, "example-1.txt")) ##' add(repo, "example-1.txt") ##' commit(repo, "First commit message") ##' ##' ## Create and add one more file ##' writeLines(c("First line in file 2.", "Second line in file 2."), ##' file.path(path, "example-2.txt")) ##' add(repo, "example-2.txt") ##' commit(repo, "Second commit message") ##' ##' ## Create a new branch 'fix' ##' checkout(repo, "fix", create = TRUE) ##' ##' ## Update 'example-1.txt' (swap words in first line) and commit ##' writeLines(c("line First in file 1.", "Second line in file 1."), ##' file.path(path, "example-1.txt")) ##' add(repo, "example-1.txt") ##' commit(repo, "Third commit message") ##' ##' checkout(repo, "master") ##' ##' ## Update 'example-2.txt' (swap words in second line) and commit ##' writeLines(c("First line in file 2.", "line Second in file 2."), ##' file.path(path, "example-2.txt")) ##' add(repo, "example-2.txt") ##' commit(repo, "Fourth commit message") ##' ##' ## Merge 'fix' ##' merge(repo, "fix") ##' ##' ## Display parents of last commit ##' parents(lookup(repo, branch_target(repository_head(repo)))) ##' ##' ## Check that last commit is a merge ##' is_merge(lookup(repo, branch_target(repository_head(repo)))) ##' } is_merge <- function(commit = NULL) { length(parents(commit)) > 1 } ##' Parents ##' ##' Get parents of a commit. ##' @param object a git_commit object. ##' @return list of git_commit objects ##' @export ##' @useDynLib git2r git2r_commit_parent_list ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' writeLines("First line.", ##' file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "First commit message") ##' ##' ## commit_1 has no parents ##' parents(commit_1) ##' ##' ## Update 'example.txt' and commit ##' writeLines(c("First line.", "Second line."), ##' file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_2 <- commit(repo, "Second commit message") ##' ##' ## commit_2 has commit_1 as parent ##' parents(commit_2) ##' } parents <- function(object = NULL) { .Call(git2r_commit_parent_list, object) } ##' @export format.git_commit <- function(x, ...) { sprintf("[%s] %s: %s", substring(x$sha, 1, 7), substring(as.character(x$author$when), 1, 10), x$summary) } ##' @export print.git_commit <- function(x, ...) { cat(format(x, ...), "\n", sep = "") invisible(x) } ##' @export summary.git_commit <- function(object, ...) { is_merge_commit <- is_merge(object) po <- parents(object) cat(sprintf("Commit: %s\n", object$sha)) if (is_merge_commit) { sha <- vapply(po, "[[", character(1), "sha") cat(sprintf("Merge: %s\n", sha[1])) cat(paste0(" ", sha[-1]), sep = "\n") } cat(sprintf(paste0("Author: %s <%s>\n", "When: %s\n\n"), object$author$name, object$author$email, as.character(object$author$when))) msg <- paste0(" ", readLines(textConnection(object$message))) cat("", sprintf("%s\n", msg)) if (is_merge_commit) { cat("\n") lapply(po, function(parent) { cat("Commit message: ", parent$sha, "\n") msg <- paste0(" ", readLines(textConnection(parent$message))) cat("", sprintf("%s\n", msg), "\n") }) } if (identical(length(po), 1L)) { df <- diff(tree(po[[1]]), tree(object)) if (length(df) > 0) { if (length(df) > 1) { cat(sprintf("%i files changed, ", length(df))) } else { cat("1 file changed, ") } cat(sprintf( "%i insertions, %i deletions\n", sum(vapply(lines_per_file(df), "[[", numeric(1), "add")), sum(vapply(lines_per_file(df), "[[", numeric(1), "del")))) plpf <- print_lines_per_file(df) hpf <- hunks_per_file(df) hunk_txt <- ifelse(hpf > 1, " hunks", ifelse(hpf > 0, " hunk", " hunk (binary file)")) phpf <- paste0(" in ", format(hpf), hunk_txt) cat(paste0(plpf, phpf), sep = "\n") } cat("\n") } invisible(NULL) } ##' @export as.data.frame.git_commit <- function(x, ...) { data.frame(sha = x$sha, summary = x$summary, message = x$message, author = x$author$name, email = x$author$email, when = as.POSIXct(x$author$when), stringsAsFactors = FALSE) } git2r/R/credential.R0000644000176200001440000001726614704731663013766 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013 - 2022 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Create a new environmental credential object ##' ##' Environmental variables can be written to the file ##' \code{.Renviron}. This file is read by \emph{R} during startup, ##' see \code{\link[base]{Startup}}. ##' @family git credential functions ##' @param username The name of the environmental variable that holds ##' the username for the authentication. ##' @param password The name of the environmental variable that holds ##' the password for the authentication. ##' @return A list of class \code{cred_env} with entries: ##' \describe{ ##' \item{username}{ ##' The name of the environmental variable that holds ##' the username for the authentication. ##' } ##' \item{password}{ ##' The name of the environmental variable that holds ##' the password for the authentication. ##' } ##' } ##' @export ##' @examples ##' \dontrun{ ##' ## Create an environmental credential object for the username and ##' ## password. ##' cred <- cred_env("NAME_OF_ENV_VARIABLE_WITH_USERNAME", ##' "NAME_OF_ENV_VARIABLE_WITH_PASSWORD") ##' repo <- repository("git2r") ##' push(repo, credentials = cred) ##' } cred_env <- function(username = NULL, password = NULL) { structure(list(username = username, password = password), class = "cred_env") } ##' Create a new personal access token credential object ##' ##' The personal access token is stored in an envrionmental variable. ##' Environmental variables can be written to the file ##' \code{.Renviron}. This file is read by \emph{R} during startup, ##' see \code{\link[base]{Startup}}. On GitHub, personal access tokens ##' function like ordinary OAuth access tokens. They can be used ##' instead of a password for Git over HTTPS, see the \dQuote{Creating ##' a personal access token} article on GitHub Docs. ##' @family git credential functions ##' @param token The name of the environmental variable that holds the ##' personal access token for the authentication. Default is ##' \code{GITHUB_PAT}. ##' @return A list of class \code{cred_token} with entry: ##' \describe{ ##' \item{token}{ ##' The name of the environmental variable that holds ##' the personal access token for the authentication. ##' } ##' } ##' @export ##' @examples ##' \dontrun{ ##' ## Create a personal access token credential object. ##' ## This example assumes that the token is stored in ##' ## the 'GITHUB_PAT' environmental variable. ##' repo <- repository("git2r") ##' cred <- cred_token() ##' push(repo, credentials = cred) ##' } cred_token <- function(token = "GITHUB_PAT") { structure(list(token = token), class = "cred_token") } ##' Create a new plain-text username and password credential object ##' ##' @family git credential functions ##' @param username The username of the credential ##' @param password The password of the credential. If getPass is installed ##' and the only input is username, \code{getPass::getPass()} will be ##' called to allow for interactive and obfuscated interactive ##' input of the password. ##' @return A list of class \code{cred_user_pass} with entries: ##' \describe{ ##' \item{username}{ ##' The username of the credential ##' } ##' \item{password}{ ##' The password of the credential ##' } ##' } ##' @export ##' @examples ##' \dontrun{ ##' ## Create a plain-text username and password credential object ##' cred_user_pass("Random Developer", "SecretPassword") ##' } cred_user_pass <- function(username = NULL, password = NULL) { if (!is.null(username)) { if (is.null(password)) { if (requireNamespace("getPass", quietly = TRUE)) { password <- getPass::getPass() } } } structure(list(username = username, password = password), class = "cred_user_pass") } ##' Create a new passphrase-protected ssh key credential object ##' ##' @family git credential functions ##' @param publickey The path to the public key of the ##' credential. Default is \code{ssh_path("id_rsa.pub")} ##' @param privatekey The path to the private key of the ##' credential. Default is \code{ssh_path("id_rsa")} ##' @param passphrase The passphrase of the credential. Default is ##' \code{character(0)}. If getPass is installed and private key ##' is passphrase protected \code{getPass::getPass()} will be ##' called to allow for interactive and obfuscated interactive ##' input of the passphrase. ##' @return A list of class \code{cred_ssh_key} with entries: ##' \describe{ ##' \item{publickey}{ ##' The path to the public key of the credential ##' } ##' \item{privatekey}{ ##' The path to the private key of the credential ##' } ##' \item{passphrase}{ ##' The passphrase of the credential ##' } ##' } ##' @export ##' @examples ##' \dontrun{ ##' ## Create a ssh key credential object. It can optionally be ##' ## passphrase-protected ##' cred <- cred_ssh_key(ssh_path("id_rsa.pub"), ssh_path("id_rsa")) ##' repo <- repository("git2r") ##' push(repo, credentials = cred) ##' } cred_ssh_key <- function(publickey = ssh_path("id_rsa.pub"), privatekey = ssh_path("id_rsa"), passphrase = character(0)) { publickey <- normalizePath(publickey, mustWork = TRUE) privatekey <- normalizePath(privatekey, mustWork = TRUE) if (length(passphrase) == 0) { if (ssh_key_needs_passphrase(privatekey)) { if (requireNamespace("getPass", quietly = TRUE)) { passphrase <- getPass::getPass() } } } structure(list(publickey = publickey, privatekey = privatekey, passphrase = passphrase), class = "cred_ssh_key") } ##' Check if private key is passphrase protected ##' @param privatekey The path to the private key of the ##' credential. Default is \code{ssh_path("id_rsa")} ##' @noRd ssh_key_needs_passphrase <- function(privatekey = ssh_path("id_rsa")) { private_content <- readLines(privatekey, n = 3) contains_encrypted <- grepl("encrypted", private_content, ignore.case = TRUE) any(contains_encrypted) } ##' Compose usual path to ssh keys ##' ##' This function provides a consistent means across OS-types to access the ##' \code{.ssh} directory. ##' ##' On Windows-based systems, ##' \code{path.expand("~")} returns \code{"C:/Users/username/Documents"}, ##' whereas the usual path to the \code{.ssh} directory is ##' \code{"C:/Users/username"}. ##' ##' On other operating systems, \code{path.expand("~")} returns the usual path ##' to the \code{.ssh} directory. ##' ##' Calling \code{ssh_path()} with no arguments will return the usual path to ##' the \code{.ssh} directory. ##' ##' @param file basename of file for which path is requested ##' @return Full path to the file ##' @export ##' @examples ##' ssh_path() ##' ssh_path("is_rsa.pub") ssh_path <- function(file = "") { file.path(home_dir(), ".ssh", file) } # Return the user's home directory regardless of operating system home_dir <- function() { if (.Platform$OS.type == "windows") { home <- Sys.getenv("USERPROFILE") } else { home <- path.expand("~") } return(home) } git2r/R/blame.R0000644000176200001440000000616414704011561012713 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Get blame for file ##' ##' @template repo-param ##' @param path Path to the file to consider ##' @return git_blame object with the following entries: ##' \describe{ ##' \item{path}{ ##' The path to the file of the blame ##' } ##' \item{hunks}{ ##' List of blame hunks ##' } ##' \item{repo}{ ##' The git_repository that contains the file ##' } ##' } ##' \describe{ ##' \item{lines_in_hunk}{ ##' The number of lines in this hunk ##' } ##' \item{final_commit_id}{ ##' The sha of the commit where this line was last changed ##' } ##' \item{final_start_line_number}{ ##' The 1-based line number where this hunk begins, in the final ##' version of the file ##' } ##' \item{final_signature}{ ##' Final committer ##' } ##' \item{orig_commit_id}{ ##' The sha of the commit where this hunk was found. This will usually ##' be the same as 'final_commit_id'. ##' } ##' \item{orig_start_line_number}{ ##' The 1-based line number where this hunk begins in the file ##' named by 'orig_path' in the commit specified by 'orig_commit_id'. ##' } ##' \item{orig_signature}{ ##' Origin committer ##' } ##' \item{orig_path}{ ##' The path to the file where this hunk originated, as of the commit ##' specified by 'orig_commit_id' ##' } ##' \item{boundary}{ ##' TRUE iff the hunk has been tracked to a boundary commit. ##' } ##' \item{repo}{ ##' The \code{git_repository} object that contains the blame hunk ##' } ##' } ##' @export ##' @useDynLib git2r git2r_blame_file ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a first user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Create a second user and change the file ##' config(repo, user.name = "Bob", user.email = "bob@@example.org") ##' writeLines(c("Hello world!", "HELLO WORLD!", "HOLA"), ##' file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "Second commit message") ##' ##' ## Check blame ##' blame(repo, "example.txt") ##' } blame <- function(repo = ".", path = NULL) { .Call(git2r_blame_file, lookup_repository(repo), path) } git2r/R/time.R0000644000176200001440000000521713565056761012606 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2019 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Time ##' ##' The class \code{git_time} stores the time a Git object was created. ##' ##' The default is to use \code{tz = "GMT"} and \code{origin = ##' "1970-01-01"}. To use your local timezone, set \code{tz = ##' Sys.timezone()}. ##' ##' @inheritParams base::as.POSIXct ##' @inheritParams base::strptime ##' @seealso \code{\link{when}} ##' @name git_time ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a first user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Create tag ##' tag(repo, "Tagname", "Tag message") ##' ##' as.POSIXct(commits(repo)[[1]]$author$when) ##' as.POSIXct(tags(repo)[[1]]$tagger$when) ##' as.POSIXct(tags(repo)[[1]]$tagger$when, tz = Sys.timezone()) ##' } NULL ##' @rdname git_time ##' @export as.character.git_time <- function(x, tz = "GMT", origin = "1970-01-01", usetz = TRUE, ...) { as.character(format(as.POSIXct(x, tz = tz, origin = origin), usetz = usetz), ...) } ##' @rdname git_time ##' @export format.git_time <- function(x, tz = "GMT", origin = "1970-01-01", usetz = TRUE, ...) { format(as.POSIXct(x, tz = tz, origin = origin), usetz = usetz, ...) } ##' @rdname git_time ##' @export as.POSIXct.git_time <- function(x, tz = "GMT", origin = "1970-01-01", ...) { as.POSIXct(x$time, tz = tz, origin = origin, ...) } ##' @rdname git_time ##' @export print.git_time <- function(x, tz = "GMT", origin = "1970-01-01", usetz = TRUE, ...) { cat(sprintf("%s\n", as.character(x, tz = tz, origin = origin, usetz = usetz, ...))) invisible(x) } git2r/R/fetch.R0000644000176200001440000001200414704120736012717 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Fetch new data and update tips ##' ##' @template repo-param ##' @param name the remote's name ##' @param credentials The credentials for remote repository ##' access. Default is NULL. To use and query an ssh-agent for the ##' ssh key credentials, let this parameter be NULL (the default). ##' @param verbose Print information each time a reference is updated ##' locally. Default is \code{TRUE}. ##' @param refspec The refs to fetch and which local refs to update, ##' see examples. Pass NULL to use the ##' \code{remote..fetch} variable. Default is ##' \code{NULL}. ##' @return invisible list of class \code{git_transfer_progress} ##' with statistics from the fetch operation: ##' \describe{ ##' \item{total_objects}{ ##' Number of objects in the packfile being downloaded ##' } ##' \item{indexed_objects}{ ##' Received objects that have been hashed ##' } ##' \item{received_objects}{ ##' Objects which have been downloaded ##' } ##' \item{total_deltas}{ ##' Total number of deltas in the pack ##' } ##' \item{indexed_deltas}{ ##' Deltas which have been indexed ##' } ##' \item{local_objects}{ ##' Locally-available objects that have been injected in order to ##' fix a thin pack ##' } ##' \item{received_bytes}{ ##' Size of the packfile received up to now ##' } ##' } ##' @export ##' @useDynLib git2r git2r_remote_fetch ##' @examples ##' \dontrun{ ##' ## Initialize three temporary repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo_1 <- tempfile(pattern="git2r-") ##' path_repo_2 <- tempfile(pattern="git2r-") ##' ##' dir.create(path_bare) ##' dir.create(path_repo_1) ##' dir.create(path_repo_2) ##' ##' bare_repo <- init(path_bare, bare = TRUE) ##' repo_1 <- clone(path_bare, path_repo_1) ##' repo_2 <- clone(path_bare, path_repo_2) ##' ##' config(repo_1, user.name = "Alice", user.email = "alice@@example.org") ##' config(repo_2, user.name = "Bob", user.email = "bob@@example.org") ##' ##' ## Add changes to repo 1 ##' writeLines("Lorem ipsum dolor sit amet", ##' con = file.path(path_repo_1, "example.txt")) ##' add(repo_1, "example.txt") ##' commit(repo_1, "Commit message") ##' ##' ## Push changes from repo 1 to origin (bare_repo) ##' push(repo_1, "origin", "refs/heads/master") ##' ##' ## Fetch changes from origin (bare_repo) to repo 2 ##' fetch(repo_2, "origin") ##' ##' ## List updated heads ##' fetch_heads(repo_2) ##' ##' ## Checking out GitHub pull requests locally ##' path <- tempfile(pattern="ghit-") ##' repo <- clone("https://github.com/leeper/ghit", path) ##' fetch(repo, "origin", refspec = "pull/13/head:refs/heads/BRANCHNAME") ##' checkout(repo, "BRANCHNAME") ##' summary(repo) ##' } fetch <- function(repo = ".", name = NULL, credentials = NULL, verbose = TRUE, refspec = NULL) { invisible(.Call(git2r_remote_fetch, lookup_repository(repo), name, credentials, "fetch", verbose, refspec)) } ##' Get updated heads during the last fetch. ##' ##' @template repo-param ##' @return list with \code{git_fetch_head} entries. NULL if there is ##' no FETCH_HEAD file. ##' @export ##' @useDynLib git2r git2r_repository_fetch_heads ##' @examples ##' \dontrun{ ##' ## Initialize three temporary repositories ##' path_bare <- tempfile(pattern="git2r-") ##' path_repo_1 <- tempfile(pattern="git2r-") ##' path_repo_2 <- tempfile(pattern="git2r-") ##' ##' dir.create(path_bare) ##' dir.create(path_repo_1) ##' dir.create(path_repo_2) ##' ##' bare_repo <- init(path_bare, bare = TRUE) ##' repo_1 <- clone(path_bare, path_repo_1) ##' repo_2 <- clone(path_bare, path_repo_2) ##' ##' config(repo_1, user.name = "Alice", user.email = "alice@@example.org") ##' config(repo_2, user.name = "Bob", user.email = "bob@@example.org") ##' ##' ## Add changes to repo 1 ##' writeLines("Lorem ipsum dolor sit amet", ##' con = file.path(path_repo_1, "example.txt")) ##' add(repo_1, "example.txt") ##' commit(repo_1, "Commit message") ##' ##' ## Push changes from repo 1 to origin (bare_repo) ##' push(repo_1, "origin", "refs/heads/master") ##' ##' ## Fetch changes from origin (bare_repo) to repo 2 ##' fetch(repo_2, "origin") ##' ##' ## List updated heads ##' fetch_heads(repo_2) ##' } fetch_heads <- function(repo = ".") { .Call(git2r_repository_fetch_heads, lookup_repository(repo)) } git2r/R/reset.R0000644000176200001440000000751514704114667012771 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Reset current HEAD to the specified state ##' ##' @param object Either a \code{git_commit}, a \code{git_repository} ##' or a character vector. If \code{object} is a ##' \code{git_commit}, HEAD is moved to the \code{git_commit}. If ##' \code{object} is a \code{git_repository}, resets the index ##' entries in the \code{path} argument to their state at HEAD. If ##' \code{object} is a character vector with paths, resets the ##' index entries in \code{object} to their state at HEAD if the ##' current working directory is in a repository. ##' @param reset_type If object is a 'git_commit', the kind of reset ##' operation to perform. 'soft' means the HEAD will be moved to ##' the commit. 'mixed' reset will trigger a 'soft' reset, plus ##' the index will be replaced with the content of the commit ##' tree. 'hard' reset will trigger a 'mixed' reset and the ##' working directory will be replaced with the content of the ##' index. ##' @param path If object is a 'git_repository', resets the index ##' entries for all paths to their state at HEAD. ##' @return invisible NULL ##' @export ##' @useDynLib git2r git2r_index_remove_bypath ##' @useDynLib git2r git2r_reset ##' @useDynLib git2r git2r_reset_default ##' @examples \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' # Configure a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "test-1.txt")) ##' add(repo, "test-1.txt") ##' commit_1 <- commit(repo, "Commit message") ##' ##' ## Change and stage the file ##' writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test-1.txt")) ##' add(repo, "test-1.txt") ##' status(repo) ##' ##' ## Unstage file ##' reset(repo, path = "test-1.txt") ##' status(repo) ##' ##' ## Make one more commit ##' add(repo, "test-1.txt") ##' commit(repo, "Next commit message") ##' ##' ## Create one more file ##' writeLines("Hello world!", file.path(path, "test-2.txt")) ##' ##' ## 'soft' reset to first commit and check status ##' reset(commit_1) ##' status(repo) ##' ##' ## 'mixed' reset to first commit and check status ##' commit(repo, "Next commit message") ##' reset(commit_1, "mixed") ##' status(repo) ##' ##' ## 'hard' reset to first commit and check status ##' add(repo, "test-1.txt") ##' commit(repo, "Next commit message") ##' reset(commit_1, "hard") ##' status(repo) ##' } reset <- function(object, reset_type = c("soft", "mixed", "hard"), path = NULL) { if (is_commit(object)) { reset_type <- switch(match.arg(reset_type), soft = 1L, mixed = 2L, hard = 3L) .Call(git2r_reset, object, reset_type) } else { object <- lookup_repository(object) if (is_empty(object)) { .Call(git2r_index_remove_bypath, object, path) } else { .Call(git2r_reset_default, object, path) } } invisible(NULL) } git2r/R/note.R0000644000176200001440000001701414704117037012601 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Default notes reference ##' ##' Get the default notes reference for a repository ##' @template repo-param ##' @return Character vector of length one with name of default notes ##' reference ##' @export ##' @useDynLib git2r git2r_note_default_ref ##' @examples ##' \dontrun{ ##' ## Create and initialize a repository in a temporary directory ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## View default notes reference ##' note_default_ref(repo) ##' } note_default_ref <- function(repo = ".") { .Call(git2r_note_default_ref, lookup_repository(repo)) } ##' Add note for a object ##' ##' @param object The object to annotate (git_blob, git_commit or ##' git_tree). ##' @param message Content of the note to add ##' @param ref Canonical name of the reference to use. Default is ##' \code{note_default_ref}. ##' @param author Signature of the notes note author ##' @param committer Signature of the notes note committer ##' @param force Overwrite existing note. Default is FALSE ##' @return git_note ##' @export ##' @useDynLib git2r git2r_note_create ##' @examples ##' \dontrun{ ##' ## Create and initialize a repository in a temporary directory ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "Commit message 1") ##' ##' ## Create another commit ##' writeLines(c("Hello world!", ##' "HELLO WORLD!"), ##' file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_2 <- commit(repo, "Commit message 2") ##' ##' ## Check that notes is an empty list ##' notes(repo) ##' ##' ## Create note in default namespace ##' note_create(commit_1, "Note-1") ##' ##' ## Create note in named (review) namespace ##' note_create(commit_1, "Note-2", ref="refs/notes/review") ##' note_create(commit_2, "Note-3", ref="review") ##' ##' ## Create note on blob and tree ##' note_create(tree(commit_1), "Note-4") ##' note_create(tree(commit_1)["example.txt"], "Note-5") ##' } note_create <- function(object = NULL, message = NULL, ref = NULL, author = NULL, committer = NULL, force = FALSE) { if (is.null(object)) stop("'object' is missing") if (!any(is_blob(object), is_commit(object), is_tree(object))) stop("'object' must be a 'git_blob', 'git_commit' or 'git_tree' object") repo <- object$repo sha <- object$sha if (is.null(ref)) ref <- note_default_ref(repo) stopifnot(is.character(ref), identical(length(ref), 1L)) if (!length(grep("^refs/notes/", ref))) ref <- paste0("refs/notes/", ref) if (is.null(author)) author <- default_signature(repo) if (is.null(committer)) committer <- default_signature(repo) .Call(git2r_note_create, repo, sha, message, ref, author, committer, force) } ##' List notes ##' ##' List all the notes within a specified namespace. ##' @template repo-param ##' @param ref Reference to read from. Default (ref = NULL) is to call ##' \code{note_default_ref}. ##' @return list with git_note objects ##' @export ##' @useDynLib git2r git2r_notes ##' @examples ##' \dontrun{ ##' ## Create and initialize a repository in a temporary directory ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "Commit message 1") ##' ##' ## Create another commit ##' writeLines(c("Hello world!", ##' "HELLO WORLD!"), ##' file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_2 <- commit(repo, "Commit message 2") ##' ##' ## Create note in default namespace ##' note_create(commit_1, "Note-1") ##' note_create(commit_1, "Note-2", force = TRUE) ##' ##' ## Create note in named (review) namespace ##' note_create(commit_1, "Note-3", ref="refs/notes/review") ##' note_create(commit_2, "Note-4", ref="review") ##' ##' ## Create note on blob and tree ##' note_create(tree(commit_1), "Note-5") ##' note_create(tree(commit_1)["example.txt"], "Note-6") ##' ##' ## List notes in default namespace ##' notes(repo) ##' ##' ## List notes in 'review' namespace ##' notes(repo, "review") ##' } notes <- function(repo = ".", ref = NULL) { repo <- lookup_repository(repo) if (is.null(ref)) ref <- note_default_ref(repo) stopifnot(is.character(ref), identical(length(ref), 1L)) if (!length(grep("^refs/notes/", ref))) ref <- paste0("refs/notes/", ref) .Call(git2r_notes, repo, ref) } ##' Remove the note for an object ##' ##' @param note The note to remove ##' @param author Signature of the notes commit author. ##' @param committer Signature of the notes commit committer. ##' @return invisible NULL ##' @export ##' @useDynLib git2r git2r_note_remove ##' @examples ##' \dontrun{ ##' ## Create and initialize a repository in a temporary directory ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "Commit message 1") ##' ##' ##' ## Create note in default namespace ##' note_1 <- note_create(commit_1, "Note-1") ##' ##' ## Create note in named (review) namespace ##' note_2 <- note_create(commit_1, "Note-2", ref="refs/notes/review") ##' ##' ## List notes in default namespace ##' notes(repo) ##' ##' ## List notes in 'review' namespace ##' notes(repo, "review") ##' ##' ## Remove notes ##' note_remove(note_1) ##' note_remove(note_2) ##' ##' ## List notes in default namespace ##' notes(repo) ##' ##' ## List notes in 'review' namespace ##' notes(repo, "review") ##' } note_remove <- function(note = NULL, author = NULL, committer = NULL) { if (!inherits(note, "git_note")) stop("'note' is not a git_note") if (is.null(author)) author <- default_signature(note$repo) if (is.null(committer)) committer <- default_signature(note$repo) .Call(git2r_note_remove, note, author, committer) invisible(NULL) } ##' @export format.git_note <- function(x, ...) { sprintf("note: %s", x$sha) } ##' @export print.git_note <- function(x, ...) { cat(format(x, ...), "\n", sep = "") invisible(x) } git2r/R/blob.R0000644000176200001440000002014514704114456012553 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Create blob from file on disk ##' ##' Read a file from the filesystem and write its content to the ##' Object Database as a loose blob. The method is vectorized and ##' accepts a vector of files to create blobs from. ##' @param repo The repository where the blob(s) will be written. Can ##' be a bare repository. A \code{git_repository} object, or a ##' path to a repository, or \code{NULL}. If the \code{repo} ##' argument is \code{NULL}, the repository is searched for with ##' \code{\link{discover_repository}} in the current working ##' directory. ##' @param path The file(s) from which the blob will be created. ##' @param relative TRUE if the file(s) from which the blob will be ##' created is relative to the repository's working dir. Default ##' is TRUE. ##' @return list of S3 class git_blob \code{objects} ##' @export ##' @useDynLib git2r git2r_blob_create_fromdisk ##' @useDynLib git2r git2r_blob_create_fromworkdir ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create blobs from files relative to workdir ##' writeLines("Hello, world!", file.path(path, "example-1.txt")) ##' writeLines("test content", file.path(path, "example-2.txt")) ##' blob_list_1 <- blob_create(repo, c("example-1.txt", ##' "example-2.txt")) ##' ##' ## Create blobs from files not relative to workdir ##' temp_file_1 <- tempfile() ##' temp_file_2 <- tempfile() ##' writeLines("Hello, world!", temp_file_1) ##' writeLines("test content", temp_file_2) ##' blob_list_2 <- blob_create(repo, c(temp_file_1, temp_file_2), ##' relative = FALSE) ##' } blob_create <- function(repo = ".", path = NULL, relative = TRUE) { repo <- lookup_repository(repo) if (isTRUE(relative)) return(.Call(git2r_blob_create_fromworkdir, repo, path)) path <- normalizePath(path, mustWork = TRUE) .Call(git2r_blob_create_fromdisk, repo, path) } ##' Content of blob ##' ##' @param blob The blob object. ##' @param split Split blob content to text lines. Default TRUE. ##' @param raw When \code{TRUE}, get the content of the blob as a raw ##' vector, else as a character vector. Default is \code{FALSE}. ##' @return The content of the blob. NA_character_ if the blob is ##' binary and \code{raw} is \code{FALSE}. ##' @export ##' @useDynLib git2r git2r_blob_content ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user and commit a file ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit(repo, "First commit message") ##' ##' ## Display content of blob. ##' content(tree(commits(repo)[[1]])["example.txt"]) ##' } content <- function(blob = NULL, split = TRUE, raw = FALSE) { result <- .Call(git2r_blob_content, blob, raw) if (isTRUE(raw)) return(result) if (isTRUE(split)) result <- strsplit(result, "\n")[[1]] result } ##' Determine the sha from a blob string ##' ##' The blob is not written to the object database. ##' @param data The string vector to hash. ##' @return A string vector with the sha for each string in data. ##' @export ##' @useDynLib git2r git2r_odb_hash ##' @examples ##' \dontrun{ ##' identical(hash(c("Hello, world!\n", ##' "test content\n")), ##' c("af5626b4a114abcb82d63db7c8082c3c4756e51b", ##' "d670460b4b4aece5915caf5c68d12f560a9fe3e4")) ##' } hash <- function(data = NULL) { .Call(git2r_odb_hash, data) } ##' Determine the sha from a blob in a file ##' ##' The blob is not written to the object database. ##' @param path The path vector with files to hash. ##' @return A vector with the sha for each file in path. ##' @export ##' @useDynLib git2r git2r_odb_hashfile ##' @examples ##' \dontrun{ ##' ## Create a file. NOTE: The line endings from writeLines gives ##' ## LF (line feed) on Unix/Linux and CRLF (carriage return, line feed) ##' ## on Windows. The example use writeChar to have more control. ##' path <- tempfile() ##' f <- file(path, "wb") ##' writeChar("Hello, world!\n", f, eos = NULL) ##' close(f) ##' ##' ## Generate hash ##' hashfile(path) ##' identical(hashfile(path), hash("Hello, world!\n")) ##' } hashfile <- function(path = NULL) { path <- normalizePath(path, mustWork = TRUE) if (any(is.na(path))) stop("Invalid 'path' argument") .Call(git2r_odb_hashfile, path) } ##' Is blob binary ##' ##' @param blob The blob \code{object}. ##' @return TRUE if binary data, FALSE if not. ##' @export ##' @useDynLib git2r git2r_blob_is_binary ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Commit a text file ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "First commit message") ##' ##' ## Check if binary ##' b_text <- tree(commit_1)["example.txt"] ##' is_binary(b_text) ##' ##' ## Commit plot file (binary) ##' x <- 1:100 ##' y <- x^2 ##' png(file.path(path, "plot.png")) ##' plot(y ~ x, type = "l") ##' dev.off() ##' add(repo, "plot.png") ##' commit_2 <- commit(repo, "Second commit message") ##' ##' ## Check if binary ##' b_png <- tree(commit_2)["plot.png"] ##' is_binary(b_png) ##' } is_binary <- function(blob = NULL) { .Call(git2r_blob_is_binary, blob) } ##' Check if object is S3 class git_blob ##' ##' @param object Check if object is S3 class git_blob ##' @return TRUE if object is S3 class git_blob, else FALSE ##' @export ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Commit a text file ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "First commit message") ##' blob_1 <- tree(commit_1)["example.txt"] ##' ##' ## Check if blob ##' is_blob(commit_1) ##' is_blob(blob_1) ##' } is_blob <- function(object) { inherits(object, "git_blob") } ##' Size in bytes of the contents of a blob ##' ##' @param x The blob \code{object} ##' @return a non-negative integer ##' @export ##' @useDynLib git2r git2r_blob_rawsize ##' @examples ##' \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Create a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Commit a text file ##' writeLines("Hello world!", file.path(path, "example.txt")) ##' add(repo, "example.txt") ##' commit_1 <- commit(repo, "First commit message") ##' blob_1 <- tree(commit_1)["example.txt"] ##' ##' ## Get length in size of bytes of the content of the blob ##' length(blob_1) ##' } length.git_blob <- function(x) { .Call(git2r_blob_rawsize, x) } ##' @export format.git_blob <- function(x, ...) { sprintf("blob: %s\nsize: %i bytes", x$sha, length(x)) } ##' @export print.git_blob <- function(x, ...) { cat(format(x, ...), "\n", sep = "") invisible(x) } git2r/R/diff.R0000644000176200001440000002471014704742534012553 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Number of files in git_diff object ##' ##' @param x The git_diff \code{object} ##' @return a non-negative integer ##' @export length.git_diff <- function(x) { length(x$files) } ##' @export print.git_diff <- function(x, ...) { cat("Old: ") if (is.character(x$old)) { cat(x$old, "\n") } else if (inherits(x$old, "git_tree")) { print(x$old) } else { cat("\n") print(x$old) } cat("New: ") if (is.character(x$new)) { cat(x$new, "\n") } else if (inherits(x$new, "git_tree")) { print(x$new) } else { cat("\n") print(x$new) } invisible(x) } lines_per_file <- function(diff) { lapply(diff$files, function(x) { del <- add <- 0 for (h in x$hunks) { for (l in h$lines) { if (l$origin == 45) { del <- del + l$num_lines } else if (l$origin == 43) { add <- add + l$num_lines } } } list(file = x$new_file, del = del, add = add) }) } print_lines_per_file <- function(diff) { lpf <- lines_per_file(diff) files <- vapply(lpf, function(x) x$file, character(1)) del <- vapply(lpf, function(x) x$del, numeric(1)) add <- vapply(lpf, function(x) x$add, numeric(1)) paste0(format(files), " | ", "-", format(del), " +", format(add)) } hunks_per_file <- function(diff) { vapply(diff$files, function(x) length(x$hunks), numeric(1)) } ##' @export summary.git_diff <- function(object, ...) { print(object) if (length(object) > 0) { plpf <- print_lines_per_file(object) hpf <- hunks_per_file(object) hunk_txt <- ifelse(hpf > 1, " hunks", ifelse(hpf > 0, " hunk", " hunk (binary file)")) phpf <- paste0(" in ", format(hpf), hunk_txt) cat("Summary:", paste0(plpf, phpf), sep = "\n") } else { cat("No changes.\n") } } ##' Changes between commits, trees, working tree, etc. ##' ##' @rdname diff-methods ##' @export ##' @useDynLib git2r git2r_diff ##' @param x A \code{git_repository} object or the old \code{git_tree} ##' object to compare to. ##' @param index \describe{ ##' \item{\emph{When object equals a git_repository}}{ ##' Whether to compare the index to HEAD. If FALSE (the default), ##' then the working tree is compared to the index. ##' } ##' \item{\emph{When object equals a git_tree}}{ ##' Whether to use the working directory (by default), or the index ##' (if set to TRUE) in the comparison to \code{object}. ##' } ##' } ##' @param as_char logical: should the result be converted to a ##' character string?. Default is FALSE. ##' @param filename If as_char is TRUE, then the diff can be written ##' to a file with name filename (the file is overwritten if it ##' exists). Default is NULL. ##' @param context_lines The number of unchanged lines that define the ##' boundary of a hunk (and to display before and after). Defaults ##' to 3. ##' @param interhunk_lines The maximum number of unchanged lines ##' between hunk boundaries before the hunks will be merged into ##' one. Defaults to 0. ##' @param old_prefix The virtual "directory" prefix for old file ##' names in hunk headers. Default is "a". ##' @param new_prefix The virtual "directory" prefix for new file ##' names in hunk headers. Defaults to "b". ##' @param id_abbrev The abbreviation length to use when formatting ##' object ids. Defaults to the value of 'core.abbrev' from the ##' config, or 7 if NULL. ##' @param path A character vector of paths / fnmatch patterns to ##' constrain diff. Default is NULL which include all paths. ##' @param max_size A size (in bytes) above which a blob will be ##' marked as binary automatically; pass a negative value to ##' disable. Defaults to 512MB when max_size is NULL. ##' @return A \code{git_diff} object if as_char is FALSE. If as_char ##' is TRUE and filename is NULL, a character string, else NULL. ##' @section Line endings: ##' ##' Different operating systems handle line endings ##' differently. Windows uses both a carriage-return character and a ##' linefeed character to represent a newline in a file. While Linux ##' and macOS use only the linefeed character for a newline in a ##' file. To avoid problems in your diffs, you can configure Git to ##' properly handle line endings using the \verb{core.autocrlf} ##' setting in the Git config file, see the Git documentation ##' (\url{https://git-scm.com/}). ##' @examples ##' \dontrun{ ##' ## Initialize a repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' ## Config user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add, commit ##' writeLines("Hello world!", file.path(path, "test.txt")) ##' add(repo, "test.txt") ##' commit(repo, "Commit message") ##' ##' ## Change the file ##' writeLines(c("Hello again!", "Here is a second line", "And a third"), ##' file.path(path, "test.txt")) ##' ##' ## diff between index and workdir ##' diff_1 <- diff(repo) ##' summary(diff_1) ##' cat(diff(repo, as_char=TRUE)) ##' ##' ## Diff between index and HEAD is empty ##' diff_2 <- diff(repo, index=TRUE) ##' summary(diff_2) ##' cat(diff(repo, index=TRUE, as_char=TRUE)) ##' ##' ## Diff between tree and working dir, same as diff_1 ##' diff_3 <- diff(tree(commits(repo)[[1]])) ##' summary(diff_3) ##' cat(diff(tree(commits(repo)[[1]]), as_char=TRUE)) ##' ##' ## Add changes, diff between index and HEAD is the same as diff_1 ##' add(repo, "test.txt") ##' diff_4 <- diff(repo, index=TRUE) ##' summary(diff_4) ##' cat(diff(repo, index=TRUE, as_char=TRUE)) ##' ##' ## Diff between tree and index ##' diff_5 <- diff(tree(commits(repo)[[1]]), index=TRUE) ##' summary(diff_5) ##' cat(diff(tree(commits(repo)[[1]]), index=TRUE, as_char=TRUE)) ##' ##' ## Diff between two trees ##' commit(repo, "Second commit") ##' tree_1 <- tree(commits(repo)[[2]]) ##' tree_2 <- tree(commits(repo)[[1]]) ##' diff_6 <- diff(tree_1, tree_2) ##' summary(diff_6) ##' cat(diff(tree_1, tree_2, as_char=TRUE)) ##' ##' ## Binary files ##' set.seed(42) ##' writeBin(as.raw((sample(0:255, 1000, replace=TRUE))), ##' con=file.path(path, "test.bin")) ##' add(repo, "test.bin") ##' diff_7 <- diff(repo, index=TRUE) ##' summary(diff_7) ##' cat(diff(repo, index=TRUE, as_char=TRUE)) ##' } diff.git_repository <- function(x, index = FALSE, as_char = FALSE, filename = NULL, context_lines = 3, interhunk_lines = 0, old_prefix = "a", new_prefix = "b", id_abbrev = NULL, path = NULL, max_size = NULL, ...) { if (isTRUE(as_char)) { ## Make sure filename is character(0) to write to a ## character vector or a character vector with path in ## order to write to a file. filename <- as.character(filename) if (any(identical(filename, NA_character_), identical(nchar(filename), 0L))) { filename <- character(0) } else if (length(filename)) { filename <- normalizePath(filename, mustWork = FALSE) } } else { ## Make sure filename is NULL filename <- NULL } if (!is.null(id_abbrev)) id_abbrev <- as.integer(id_abbrev) if (!is.null(max_size)) max_size <- as.integer(max_size) .Call(git2r_diff, x, NULL, NULL, index, filename, as.integer(context_lines), as.integer(interhunk_lines), old_prefix, new_prefix, id_abbrev, path, max_size) } ##' @rdname diff-methods ##' @param new_tree The new git_tree object to compare, or NULL. If ##' NULL, then we use the working directory or the index (see the ##' \code{index} argument). ##' @param ... Not used. ##' @export ##' @useDynLib git2r git2r_diff diff.git_tree <- function(x, new_tree = NULL, index = FALSE, as_char = FALSE, filename = NULL, context_lines = 3, interhunk_lines = 0, old_prefix = "a", new_prefix = "b", id_abbrev = NULL, path = NULL, max_size = NULL, ...) { if (isTRUE(as_char)) { ## Make sure filename is character(0) to write to a character ## vector or a character vector with path in order to write to ## a file. filename <- as.character(filename) if (any(identical(filename, NA_character_), identical(nchar(filename), 0L))) { filename <- character(0) } else if (length(filename)) { filename <- normalizePath(filename, mustWork = FALSE) } } else { ## Make sure filename is NULL filename <- NULL } if (!is.null(new_tree)) { if (!inherits(new_tree, "git_tree")) { stop("Not a git tree") } if (x$repo$path != new_tree$repo$path) { stop("Cannot compare trees in different repositories") } } if (!is.null(id_abbrev)) id_abbrev <- as.integer(id_abbrev) if (!is.null(max_size)) max_size <- as.integer(max_size) .Call(git2r_diff, NULL, x, new_tree, index, filename, as.integer(context_lines), as.integer(interhunk_lines), old_prefix, new_prefix, id_abbrev, path, max_size) } ##' @export base::diff git2r/R/merge.R0000644000176200001440000001067414704742530012742 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ##' Find a merge base between two commits ##' ##' @param one One of the commits ##' @param two The other commit ##' @return git_commit ##' @export ##' @useDynLib git2r git2r_merge_base ##' @examples \dontrun{ ##' ## Create a directory in tempdir ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' ##' ## Initialize a repository ##' repo <- init(path) ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' ## Create a file, add and commit ##' writeLines("Master branch", file.path(path, "master_branch.txt")) ##' add(repo, "master_branch.txt") ##' commit_1 <- commit(repo, "Commit message 1") ##' ##' ## Create first branch, checkout, add file and commit ##' branch_1 <- branch_create(commit_1, "branch_1") ##' checkout(branch_1) ##' writeLines("Branch 1", file.path(path, "branch_1.txt")) ##' add(repo, "branch_1.txt") ##' commit_2 <- commit(repo, "Commit message branch_1") ##' ##' ## Create second branch, checkout, add file and commit ##' branch_2 <- branch_create(commit_1, "branch_2") ##' checkout(branch_2) ##' writeLines("Branch 2", file.path(path, "branch_2.txt")) ##' add(repo, "branch_2.txt") ##' commit_3 <- commit(repo, "Commit message branch_2") ##' ##' ## Check that merge base equals commit_1 ##' stopifnot(identical(merge_base(commit_2, commit_3), commit_1)) ##' } merge_base <- function(one = NULL, two = NULL) { .Call(git2r_merge_base, one, two) } ##' Merge a branch into HEAD ##' ##' @rdname merge ##' @param x A path (default '.') to a repository, or a ##' \code{git_repository} object, or a \code{git_branch}. ##' @param y If \code{x} is a \code{git_repository}, the name of the ##' branch to merge into HEAD. Not used if \code{x} is a ##' \code{git_branch}. ##' @param commit_on_success If there are no conflicts written to the ##' index, the merge commit will be committed. Default is TRUE. ##' @param merger Who made the merge. The default (\code{NULL}) is to ##' use \code{default_signature} for the repository. ##' @param fail If a conflict occurs, exit immediately instead of ##' attempting to continue resolving conflicts. Default is ##' \code{FALSE}. ##' @param ... Additional arguments (unused). ##' @template return-git_merge_result ##' @export ##' @useDynLib git2r git2r_merge_branch ##' @template merge-example merge.git_branch <- function(x, y = NULL, commit_on_success = TRUE, merger = NULL, fail = FALSE, ...) { if (is.null(merger)) merger <- default_signature(x$repo) .Call(git2r_merge_branch, x, merger, commit_on_success, fail) } ##' @export ##' @rdname merge merge.git_repository <- function(x, y = NULL, commit_on_success = TRUE, merger = NULL, fail = FALSE, ...) { ## Check branch argument if (!is.character(y) || !identical(length(y), 1L)) stop("'branch' must be a character vector of length one") b <- branches(x) b <- b[vapply(b, "[[", character(1), "name") == y][[1]] merge.git_branch(b, commit_on_success = commit_on_success, merger = merger, fail = fail) } ##' @export ##' @rdname merge merge.character <- function(x = ".", y = NULL, commit_on_success = TRUE, merger = NULL, fail = FALSE, ...) { x <- lookup_repository(x) merge.git_repository(x, y, commit_on_success, merger, fail) } ##' @export base::merge ##' @export format.git_merge_result <- function(x, ...) { if (isTRUE(x$up_to_date)) return("Already up-to-date") if (isTRUE(x$conflicts)) return("Merge: Conflicts") if (isTRUE(x$fast_forward)) return("Merge: Fast-forward") return("Merge") } ##' @export print.git_merge_result <- function(x, ...) { cat(format(x, ...), "\n", sep = "") invisible(x) } git2r/R/stash.R0000644000176200001440000002601314704025462012755 0ustar liggesusers## git2r, R bindings to the libgit2 library. ## Copyright (C) 2013-2024 The git2r contributors ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License, version 2, ## as published by the Free Software Foundation. ## ## git2r is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License along ## with this program; if not, write to the Free Software Foundation, Inc., ## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. stash_index <- function(object, index) { if (inherits(object, "git_stash")) { ## Determine the index of the stash in the stash list index <- match(object$sha, vapply(stash_list(object$repo), "[[", character(1), "sha")) } ## The stash list is zero-based if (abs(index - round(index)) >= .Machine$double.eps^0.5) stop("'index' must be an integer") as.integer(index) - 1L } stash_object <- function(object) { if (inherits(object, "git_stash")) return(object$repo) lookup_repository(object) } ##' Apply stash ##' ##' Apply a single stashed state from the stash list. ##' ##' If local changes in the working directory conflict with changes in ##' the stash then an error will be raised. In this case, the index ##' will always remain unmodified and all files in the working ##' directory will remain unmodified. However, if you are restoring ##' untracked files or ignored files and there is a conflict when ##' applying the modified files, then those files will remain in the ##' working directory. ##' @param object path to a repository, or a \code{git_repository} ##' object, or the stash \code{object} to pop. Default is a ##' \code{path = '.'} to a reposiory. ##' @param index The index to the stash to apply. Only used when ##' \code{object} is a path to a repository or a ##' \code{git_repository} object. Default is \code{index = 1}. ##' @return invisible NULL ##' @export ##' @useDynLib git2r git2r_stash_apply ##' @examples \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' # Configure a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' # Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "test.txt")) ##' add(repo, 'test.txt') ##' commit(repo, "Commit message") ##' ##' # Change file ##' writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) ##' ##' # Create stash in repository ##' stash(repo) ##' ##' # Change file ##' writeLines(c("Hello world!", "HeLlO wOrLd!"), file.path(path, "test.txt")) ##' ##' # Create stash in repository ##' stash(repo) ##' ##' # View stashes ##' stash_list(repo) ##' ##' # Read file ##' readLines(file.path(path, "test.txt")) ##' ##' # Apply latest git_stash object in repository ##' stash_apply(stash_list(repo)[[1]]) ##' ##' # Read file ##' readLines(file.path(path, "test.txt")) ##' ##' # View stashes ##' stash_list(repo) ##' } stash_apply <- function(object = ".", index = 1) { .Call(git2r_stash_apply, stash_object(object), stash_index(object, index)) invisible(NULL) } ##' Drop stash ##' ##' @param object path to a repository, or a \code{git_repository} ##' object, or the stash \code{object} to drop. Default is a ##' \code{path = '.'} to a reposiory. ##' @param index The index to the stash to drop. Only used when ##' \code{object} is a path to a repository or a ##' \code{git_repository} object. Default is \code{index = 1}. ##' @return invisible NULL ##' @export ##' @useDynLib git2r git2r_stash_drop ##' @examples \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' # Configure a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' # Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "test.txt")) ##' add(repo, 'test.txt') ##' commit(repo, "Commit message") ##' ##' # Change file ##' writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) ##' ##' # Create stash in repository ##' stash(repo) ##' ##' # Change file ##' writeLines(c("Hello world!", "HeLlO wOrLd!"), file.path(path, "test.txt")) ##' ##' # Create stash in repository ##' stash(repo) ##' ##' # View stashes ##' stash_list(repo) ##' ##' # Drop git_stash object in repository ##' stash_drop(stash_list(repo)[[1]]) ##' ##' ## Drop stash using an index to stash ##' stash_drop(repo, 1) ##' ##' # View stashes ##' stash_list(repo) ##' } stash_drop <- function(object = ".", index = 1) { .Call(git2r_stash_drop, stash_object(object), stash_index(object, index)) invisible(NULL) } ##' Stash ##' ##' @template repo-param ##' @param message Optional description. Defaults to current time. ##' @param index All changes already added to the index are left ##' intact in the working directory. Default is FALSE ##' @param untracked All untracked files are also stashed and then ##' cleaned up from the working directory. Default is FALSE ##' @param ignored All ignored files are also stashed and then cleaned ##' up from the working directory. Default is FALSE ##' @param stasher Signature with stasher and time of stash ##' @return invisible \code{git_stash} object if anything to stash ##' else NULL ##' @export ##' @useDynLib git2r git2r_stash_save ##' @examples \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' # Configure a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' # Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "test.txt")) ##' add(repo, 'test.txt') ##' commit(repo, "Commit message") ##' ##' # Change file ##' writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) ##' ##' # Check status of repository ##' status(repo) ##' ##' # Create stash in repository ##' stash(repo) ##' ##' # Check status of repository ##' status(repo) ##' ##' # View stash ##' stash_list(repo) ##' } stash <- function(repo = ".", message = as.character(Sys.time()), index = FALSE, untracked = FALSE, ignored = FALSE, stasher = NULL) { repo <- lookup_repository(repo) if (is.null(stasher)) stasher <- default_signature(repo) invisible(.Call(git2r_stash_save, repo, message, index, untracked, ignored, stasher)) } ##' List stashes in repository ##' ##' @template repo-param ##' @return list of stashes in repository ##' @export ##' @useDynLib git2r git2r_stash_list ##' @examples \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' # Configure a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' # Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "test-1.txt")) ##' add(repo, 'test-1.txt') ##' commit(repo, "Commit message") ##' ##' # Make one more commit ##' writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test-1.txt")) ##' add(repo, 'test-1.txt') ##' commit(repo, "Next commit message") ##' ##' # Create one more file ##' writeLines("Hello world!", file.path(path, "test-2.txt")) ##' ##' # Check that there are no stashes ##' stash_list(repo) ##' ##' # Stash ##' stash(repo) ##' ##' # Only untracked changes, therefore no stashes ##' stash_list(repo) ##' ##' # Stash and include untracked changes ##' stash(repo, "Stash message", untracked=TRUE) ##' ##' # View stash ##' stash_list(repo) ##' } stash_list <- function(repo = ".") { .Call(git2r_stash_list, lookup_repository(repo)) } ##' Pop stash ##' ##' Apply a single stashed state from the stash list and remove it ##' from the list if successful. ##' @param object path to a repository, or a \code{git_repository} ##' object, or the stash \code{object} to pop. Default is a ##' \code{path = '.'} to a reposiory. ##' @param index The index to the stash to pop. Only used when ##' \code{object} is a path to a repository or a ##' \code{git_repository} object. Default is \code{index = 1}. ##' @return invisible NULL ##' @export ##' @useDynLib git2r git2r_stash_pop ##' @examples \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' # Configure a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' # Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "test.txt")) ##' add(repo, 'test.txt') ##' commit(repo, "Commit message") ##' ##' # Change file ##' writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) ##' ##' # Create stash in repository ##' stash(repo) ##' ##' # Change file ##' writeLines(c("Hello world!", "HeLlO wOrLd!"), file.path(path, "test.txt")) ##' ##' # Create stash in repository ##' stash(repo) ##' ##' # View stashes ##' stash_list(repo) ##' ##' # Read file ##' readLines(file.path(path, "test.txt")) ##' ##' # Pop latest git_stash object in repository ##' stash_pop(stash_list(repo)[[1]]) ##' ##' # Read file ##' readLines(file.path(path, "test.txt")) ##' ##' # View stashes ##' stash_list(repo) ##' } stash_pop <- function(object = ".", index = 1) { .Call(git2r_stash_pop, stash_object(object), stash_index(object, index)) invisible(NULL) } ##' @export format.git_stash <- function(x, ...) { x$message } ##' @export print.git_stash <- function(x, ...) { cat(format(x, ...), "\n", sep = "") invisible(x) } ##' Summary of a stash ##' ##' @param object The stash \code{object} ##' @param ... Additional arguments affecting the summary produced. ##' @return None (invisible 'NULL'). ##' @export ##' @examples \dontrun{ ##' ## Initialize a temporary repository ##' path <- tempfile(pattern="git2r-") ##' dir.create(path) ##' repo <- init(path) ##' ##' # Configure a user ##' config(repo, user.name = "Alice", user.email = "alice@@example.org") ##' ##' # Create a file, add and commit ##' writeLines("Hello world!", file.path(path, "test.txt")) ##' add(repo, 'test.txt') ##' commit(repo, "Commit message") ##' ##' # Change file ##' writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) ##' ##' # Create stash in repository ##' stash(repo, "Stash message") ##' ##' # View summary of stash ##' summary(stash_list(repo)[[1]]) ##' } summary.git_stash <- function(object, ...) { cat(sprintf(paste0("message: %s\n", "stasher: %s <%s>\n", "when: %s\n", "sha: %s\n\n"), object$summary, object$author$name, object$author$email, as.character(object$author$when), object$sha)) } git2r/cleanup0000755000176200001440000000015514705132220012653 0ustar liggesusers#!/bin/sh rm -f config.* rm -f src/Makevars rm -rf autom4te.cache rm -f src/*.o rm -f src/*.so rm -rf .deps git2r/src/0000755000176200001440000000000014705127216012075 5ustar liggesusersgit2r/src/git2r_signature.h0000644000176200001440000000206313273077667015374 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_signature_h #define INCLUDE_git2r_signature_h #include #include #include SEXP git2r_signature_default(SEXP repo); int git2r_signature_from_arg(git_signature **out, SEXP signature); void git2r_signature_init(const git_signature *source, SEXP dest); #endif git2r/src/git2r_error.c0000644000176200001440000001131113671131056014474 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2020 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include /** * Error messages */ const char git2r_err_alloc_memory_buffer[] = "Unable to allocate memory buffer"; const char git2r_err_branch_not_local[] = "'branch' is not local"; const char git2r_err_branch_not_remote[] = "'branch' is not remote"; const char git2r_err_checkout_tree[] = "Expected commit, tag or tree"; const char git2r_err_invalid_refname[] = "Invalid reference name"; const char git2r_err_invalid_remote[] = "Invalid remote name"; const char git2r_err_invalid_repository[] = "Invalid repository"; const char git2r_err_nothing_added_to_commit[] = "Nothing added to commit"; const char git2r_err_object_type[] = "Unexpected object type."; const char git2r_err_reference[] = "Unexpected reference type"; const char git2r_err_repo_init[] = "Unable to init repository"; const char git2r_err_revparse_not_found[] = "Requested object could not be found"; const char git2r_err_revparse_single[] = "Expected commit, tag or tree"; const char git2r_err_ssl_cert_locations[] = "Either 'filename' or 'path' may be 'NULL', but not both"; const char git2r_err_unexpected_config_level[] = "Unexpected config level"; const char git2r_err_unable_to_authenticate[] = "Unable to authenticate with supplied credentials"; /** * Error messages specific to argument checking */ const char git2r_err_blob_arg[] = "must be an S3 class git_blob"; const char git2r_err_branch_arg[] = "must be an S3 class git_branch"; const char git2r_err_commit_arg[] = "must be an S3 class git_commit"; const char git2r_err_commit_stash_arg[] = "must be an S3 class git_commit or an S3 class git_stash"; const char git2r_err_credentials_arg[] = "must be an S3 class with credentials"; const char git2r_err_diff_arg[] = "Invalid diff parameters"; const char git2r_err_fetch_heads_arg[] = "must be a list of S3 git_fetch_head objects"; const char git2r_err_filename_arg[] = "must be either 1) NULL, or 2) a character vector of length 0 or 3) a character vector of length 1 and nchar > 0"; const char git2r_err_sha_arg[] = "must be a sha value"; const char git2r_err_integer_arg[] = "must be an integer vector of length one with non NA value"; const char git2r_err_integer_gte_zero_arg[] = "must be an integer vector of length one with value greater than or equal to zero"; const char git2r_err_list_arg[] = "must be a list"; const char git2r_err_logical_arg[] = "must be logical vector of length one with non NA value"; const char git2r_err_note_arg[] = "must be an S3 class git_note"; const char git2r_err_signature_arg[] = "must be an S3 class git_signature"; const char git2r_err_string_arg[] = "must be a character vector of length one with non NA value"; const char git2r_err_string_vec_arg[] = "must be a character vector"; const char git2r_err_tag_arg[] = "must be an S3 class git_tag"; const char git2r_err_tree_arg[] = "must be an S3 class git_tree"; /** * Raise error * * @param func_name The name of the function that raise the error. * @param err Optional error argument from libgit2 with the git_error * object that was last generated. * @param msg1 Optional text argument with error message, used if * 'err' is NULL. * @param msg2 Optional text argument, e.g. used during argument * checking to pass the error message to the variable name in 'msg1'. */ void attribute_hidden git2r_error( const char *func_name, const git_error *err, const char *msg1, const char *msg2) { if (func_name && err && err->message) Rf_error("Error in '%s': %s\n", func_name, err->message); else if (func_name && msg1 && msg2) Rf_error("Error in '%s': %s %s\n", func_name, msg1, msg2); else if (func_name && msg1) Rf_error("Error in '%s': %s\n", func_name, msg1); else if (func_name) Rf_error("Error in '%s'\n", func_name); else Rf_error("Unexpected error. Please report at" " https://github.com/ropensci/git2r/issues\n"); } git2r/src/git2r_note.h0000644000176200001440000000221713137360640014322 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_note_h #define INCLUDE_git2r_note_h #include #include SEXP git2r_note_create( SEXP repo, SEXP sha, SEXP message, SEXP ref, SEXP author, SEXP committer, SEXP force); SEXP git2r_note_default_ref(SEXP repo); SEXP git2r_notes(SEXP repo, SEXP ref); SEXP git2r_note_remove( SEXP note, SEXP author, SEXP committer); #endif git2r/src/git2r_status.h0000644000176200001440000000176613137360640014710 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2016 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_status_h #define INCLUDE_git2r_status_h #include #include SEXP git2r_status_list( SEXP repo, SEXP staged, SEXP unstaged, SEXP untracked, SEXP all_untracked, SEXP ignored); #endif git2r/src/git2r_stash.c0000644000176200001440000002273114700265130014470 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_commit.h" #include "git2r_error.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_signature.h" #include "git2r_stash.h" /** * Data structure to hold information when iterating over stash * objects. */ typedef struct { size_t n; SEXP list; SEXP repo; git_repository *repository; } git2r_stash_list_cb_data; /** * Apply a single stashed state from the stash list. * * @param repo S3 class git_repository that contains the stash * @param index The index to the stash. 0 is the most recent stash. * @return R_NilValue */ SEXP attribute_hidden git2r_stash_apply( SEXP repo, SEXP index) { int error; git_repository *repository = NULL; if (git2r_arg_check_integer_gte_zero(index)) git2r_error(__func__, NULL, "'index'", git2r_err_integer_gte_zero_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_stash_apply(repository, INTEGER(index)[0], NULL); if (error == GIT_ENOTFOUND) error = 0; git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Remove a stash from the stash list * * @param repo S3 class git_repository that contains the stash * @param index The index to the stash. 0 is the most recent stash. * @return R_NilValue */ SEXP attribute_hidden git2r_stash_drop( SEXP repo, SEXP index) { int error; git_repository *repository = NULL; if (git2r_arg_check_integer_gte_zero(index)) git2r_error(__func__, NULL, "'index'", git2r_err_integer_gte_zero_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_stash_drop(repository, INTEGER(index)[0]); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Apply a single stashed state from the stash list and remove it from * the list if successful. * * @param repo S3 class git_repository that contains the stash * @param index The index to the stash. 0 is the most recent stash. * @return R_NilValue */ SEXP attribute_hidden git2r_stash_pop( SEXP repo, SEXP index) { int error; git_repository *repository = NULL; if (git2r_arg_check_integer_gte_zero(index)) git2r_error(__func__, NULL, "'index'", git2r_err_integer_gte_zero_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_stash_pop(repository, INTEGER(index)[0], NULL); if (error == GIT_ENOTFOUND) error = 0; git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Init slots in S3 class git_stash * * @param source The commit oid of the stashed state. * @param repository The repository * @param repo S3 class git_repository that contains the stash * @param dest S3 class git_stash to initialize * @return int 0 on success, or an error code. */ static int git2r_stash_init( const git_oid *source, git_repository *repository, SEXP repo, SEXP dest) { int error; git_commit *commit = NULL; error = git_commit_lookup(&commit, repository, source); if (error) return error; git2r_commit_init(commit, repo, dest); git_commit_free(commit); return 0; } /** * Callback when iterating over stashes * * @param index The position within the stash list. 0 points to the * most recent stashed state. * @param message The stash message. * @param stash_id The commit oid of the stashed state. * @param payload Pointer to a git2r_stash_list_cb_data data structure. * @return 0 if OK, else error code */ static int git2r_stash_list_cb( size_t index, const char* message, const git_oid *stash_id, void *payload) { int error = 0, nprotect = 0; SEXP stash, class; git2r_stash_list_cb_data *cb_data = (git2r_stash_list_cb_data*)payload; GIT2R_UNUSED(index); GIT2R_UNUSED(message); /* Check if we have a list to populate */ if (!Rf_isNull(cb_data->list)) { PROTECT(class = Rf_allocVector(STRSXP, 2)); nprotect++; SET_STRING_ELT(class, 0, Rf_mkChar("git_stash")); SET_STRING_ELT(class, 1, Rf_mkChar("git_commit")); PROTECT(stash = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); nprotect++; Rf_setAttrib(stash, R_ClassSymbol, class); error = git2r_stash_init( stash_id, cb_data->repository, cb_data->repo, stash); if (error) goto cleanup; SET_VECTOR_ELT(cb_data->list, cb_data->n, stash); } cb_data->n += 1; cleanup: if (nprotect) UNPROTECT(nprotect); return error; } /** * List stashes in a repository * * @param repo S3 class git_repository * @return VECXSP with S3 objects of class git_stash */ SEXP attribute_hidden git2r_stash_list( SEXP repo) { SEXP list = R_NilValue; int error, nprotect = 0; git2r_stash_list_cb_data cb_data = {0, R_NilValue, R_NilValue, NULL}; git_repository *repository = NULL; repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); /* Count number of stashes before creating the list */ error = git_stash_foreach(repository, &git2r_stash_list_cb, &cb_data); if (error) goto cleanup; PROTECT(list = Rf_allocVector(VECSXP, cb_data.n)); nprotect++; cb_data.n = 0; cb_data.list = list; cb_data.repo = repo; cb_data.repository = repository; error = git_stash_foreach(repository, &git2r_stash_list_cb, &cb_data); cleanup: git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return list; } /** * Stash * * @param repo The repository * @param message Optional description * @param index All changes already added to the index are left * intact in the working directory. Default is FALSE * @param untracked All untracked files are also stashed and then * cleaned up from the working directory. Default is FALSE * @param ignored All ignored files are also stashed and then cleaned * up from the working directory. Default is FALSE * @param stasher Signature with stasher and time of stash * @return S3 class git_stash */ SEXP attribute_hidden git2r_stash_save( SEXP repo, SEXP message, SEXP index, SEXP untracked, SEXP ignored, SEXP stasher) { int error, nprotect = 0; SEXP result = R_NilValue, class; git_oid oid; git_stash_flags flags = GIT_STASH_DEFAULT; git_commit *commit = NULL; git_repository *repository = NULL; git_signature *c_stasher = NULL; if (git2r_arg_check_logical(index)) git2r_error(__func__, NULL, "'index'", git2r_err_logical_arg); if (git2r_arg_check_logical(untracked)) git2r_error(__func__, NULL, "'untracked'", git2r_err_logical_arg); if (git2r_arg_check_logical(ignored)) git2r_error(__func__, NULL, "'ignored'", git2r_err_logical_arg); if (git2r_arg_check_signature(stasher)) git2r_error(__func__, NULL, "'stasher'", git2r_err_signature_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); if (LOGICAL(index)[0]) flags |= GIT_STASH_KEEP_INDEX; if (LOGICAL(untracked)[0]) flags |= GIT_STASH_INCLUDE_UNTRACKED; if (LOGICAL(ignored)[0]) flags |= GIT_STASH_INCLUDE_IGNORED; error = git2r_signature_from_arg(&c_stasher, stasher); if (error) goto cleanup; error = git_stash_save( &oid, repository, c_stasher, CHAR(STRING_ELT(message, 0)), flags); if (error) { if (GIT_ENOTFOUND == error) error = GIT_OK; goto cleanup; } PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, class = Rf_allocVector(STRSXP, 2)); SET_STRING_ELT(class, 0, Rf_mkChar("git_stash")); SET_STRING_ELT(class, 1, Rf_mkChar("git_commit")); error = git2r_stash_init(&oid, repository, repo, result); cleanup: git_commit_free(commit); git_signature_free(c_stasher); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } git2r/src/git2r_odb.h0000644000176200001440000000175613226357765014145 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_odb_h #define INCLUDE_git2r_odb_h #include #include SEXP git2r_odb_blobs(SEXP repo); SEXP git2r_odb_hash(SEXP data); SEXP git2r_odb_hashfile(SEXP path); SEXP git2r_odb_objects(SEXP repo); #endif git2r/src/git2r_oid.c0000644000176200001440000000242113671131056014120 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2020 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "git2r_oid.h" /** * Get oid from sha SEXP * * @param sha A character vector with sha's. The length * can be less than 40 bytes. * @param oid result is written into the oid * @return void */ void attribute_hidden git2r_oid_from_sha_sexp( SEXP sha, git_oid *oid) { size_t len; len = LENGTH(STRING_ELT(sha, 0)); if (GIT_OID_HEXSZ == len) git_oid_fromstr(oid, CHAR(STRING_ELT(sha, 0))); else git_oid_fromstrn(oid, CHAR(STRING_ELT(sha, 0)), len); } git2r/src/git2r_odb.c0000644000176200001440000003456614700531047014126 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_error.h" #include "git2r_odb.h" #include "git2r_repository.h" /** * Determine the sha of character vectors without writing to the * object data base. * * @param data STRSXP with character vectors to hash * @return A STRSXP with character vector of sha values */ SEXP attribute_hidden git2r_odb_hash( SEXP data) { SEXP result; int error = GIT_OK; size_t len, i; char sha[GIT_OID_HEXSZ + 1]; git_oid oid; if (git2r_arg_check_string_vec(data)) git2r_error(__func__, NULL, "'data'", git2r_err_string_vec_arg); len = Rf_length(data); PROTECT(result = Rf_allocVector(STRSXP, len)); for (i = 0; i < len; i++) { if (NA_STRING == STRING_ELT(data, i)) { SET_STRING_ELT(result, i, NA_STRING); } else { error = git_odb_hash(&oid, CHAR(STRING_ELT(data, i)), LENGTH(STRING_ELT(data, i)), GIT_OBJECT_BLOB); if (error) break; git_oid_fmt(sha, &oid); sha[GIT_OID_HEXSZ] = '\0'; SET_STRING_ELT(result, i, Rf_mkChar(sha)); } } UNPROTECT(1); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Determine the sha of files without writing to the object data * base. * * @param path STRSXP with file vectors to hash * @return A STRSXP with character vector of sha values */ SEXP attribute_hidden git2r_odb_hashfile( SEXP path) { SEXP result; int error = GIT_OK; size_t len, i; char sha[GIT_OID_HEXSZ + 1]; git_oid oid; if (git2r_arg_check_string_vec(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_vec_arg); len = Rf_length(path); PROTECT(result = Rf_allocVector(STRSXP, len)); for (i = 0; i < len; i++) { if (NA_STRING == STRING_ELT(path, i)) { SET_STRING_ELT(result, i, NA_STRING); } else { error = git_odb_hashfile(&oid, CHAR(STRING_ELT(path, i)), GIT_OBJECT_BLOB); if (error) break; git_oid_fmt(sha, &oid); sha[GIT_OID_HEXSZ] = '\0'; SET_STRING_ELT(result, i, Rf_mkChar(sha)); } } UNPROTECT(1); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Data structure to hold information when iterating over objects. */ typedef struct { size_t n; SEXP list; git_odb *odb; } git2r_odb_objects_cb_data; /** * Add object * * @param oid Oid of the object * @param list The list to hold the S3 class git_object * @param i The index to the list item * @param type The type of the object * @param len The length of the object * @param repo The S3 class that contains the object * @return void */ static void git2r_add_object( const git_oid *oid, SEXP list, size_t i, const char *type, size_t len) { int j = 0; char sha[GIT_OID_HEXSZ + 1]; /* Sha */ git_oid_fmt(sha, oid); sha[GIT_OID_HEXSZ] = '\0'; SET_STRING_ELT(VECTOR_ELT(list, j++), i, Rf_mkChar(sha)); /* Type */ SET_STRING_ELT(VECTOR_ELT(list, j++), i, Rf_mkChar(type)); /* Length */ INTEGER(VECTOR_ELT(list, j++))[i] = len; } /** * Callback when iterating over objects * * @param oid Oid of the object * @param payload Payload data * @return int 0 or error code */ static int git2r_odb_objects_cb( const git_oid *oid, void *payload) { int error; size_t len; git_object_t type; git2r_odb_objects_cb_data *p = (git2r_odb_objects_cb_data*)payload; error = git_odb_read_header(&len, &type, p->odb, oid); if (error) return error; switch(type) { case GIT_OBJECT_COMMIT: if (!Rf_isNull(p->list)) git2r_add_object(oid, p->list, p->n, "commit", len); break; case GIT_OBJECT_TREE: if (!Rf_isNull(p->list)) git2r_add_object(oid, p->list, p->n, "tree", len); break; case GIT_OBJECT_BLOB: if (!Rf_isNull(p->list)) git2r_add_object(oid, p->list, p->n, "blob", len); break; case GIT_OBJECT_TAG: if (!Rf_isNull(p->list)) git2r_add_object(oid, p->list, p->n, "tag", len); break; default: return 0; } p->n += 1; return 0; } /** * List all objects available in the database * * @param repo S3 class git_repository * @return list with sha's for commit's, tree's, blob's and tag's */ SEXP attribute_hidden git2r_odb_objects( SEXP repo) { const char *names[] = {"sha", "type", "len", ""}; int i, error, nprotect = 0; SEXP result = R_NilValue; git2r_odb_objects_cb_data cb_data = {0, R_NilValue, NULL}; git_odb *odb = NULL; git_repository *repository = NULL; repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_repository_odb(&odb, repository); if (error) goto cleanup; cb_data.odb = odb; /* Count number of objects before creating the list */ error = git_odb_foreach(odb, &git2r_odb_objects_cb, &cb_data); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, names)); nprotect++; i = 0; SET_VECTOR_ELT(result, i++, Rf_allocVector(STRSXP, cb_data.n)); SET_VECTOR_ELT(result, i++, Rf_allocVector(STRSXP, cb_data.n)); SET_VECTOR_ELT(result, i, Rf_allocVector(INTSXP, cb_data.n)); cb_data.list = result; cb_data.n = 0; error = git_odb_foreach(odb, &git2r_odb_objects_cb, &cb_data); cleanup: git_repository_free(repository); git_odb_free(odb); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Data structure to hold information when iterating over blobs. */ typedef struct { size_t n; SEXP list; git_repository *repository; git_odb *odb; } git2r_odb_blobs_cb_data; /** * Add blob entry to list * * @param entry The tree entry (blob) to add * @param odb The object database * @param list The list to hold the blob information * @param i The vector index of the list items to use for the blob information * @param path The path to the tree relative to the repository workdir * @param commit The commit that contains the root tree of the iteration * @param author The author of the commit * @param when Time of the commit * @return 0 or error code */ static int git2r_odb_add_blob( const git_tree_entry *entry, git_odb *odb, SEXP list, size_t i, const char *path, const char *commit, const char *author, double when) { int error; int j = 0; size_t len; git_object_t type; char sha[GIT_OID_HEXSZ + 1]; /* Sha */ git_oid_fmt(sha, git_tree_entry_id(entry)); sha[GIT_OID_HEXSZ] = '\0'; SET_STRING_ELT(VECTOR_ELT(list, j++), i, Rf_mkChar(sha)); /* Path */ SET_STRING_ELT(VECTOR_ELT(list, j++), i, Rf_mkChar(path)); /* Name */ SET_STRING_ELT(VECTOR_ELT(list, j++), i, Rf_mkChar(git_tree_entry_name(entry))); /* Length */ error = git_odb_read_header(&len, &type, odb, git_tree_entry_id(entry)); if (error) return error; INTEGER(VECTOR_ELT(list, j++))[i] = len; /* Commit sha */ SET_STRING_ELT(VECTOR_ELT(list, j++), i, Rf_mkChar(commit)); /* Author */ SET_STRING_ELT(VECTOR_ELT(list, j++), i, Rf_mkChar(author)); /* When */ REAL(VECTOR_ELT(list, j++))[i] = when; return GIT_OK; } /** * Recursively iterate over all tree's * * @param tree The tree to iterate over * @param path The path to the tree relative to the repository workdir * @param commit The commit that contains the root tree of the iteration * @param author The author of the commit * @param when Time of the commit * @param data The callback data when iterating over odb objects * @return 0 or error code */ static int git2r_odb_tree_blobs( const git_tree *tree, const char *path, const char *commit, const char *author, double when, git2r_odb_blobs_cb_data *data) { int error; size_t i, n; n = git_tree_entrycount(tree); for (i = 0; i < n; ++i) { const git_tree_entry *entry; entry = git_tree_entry_byindex(tree, i); switch (git_tree_entry_type(entry)) { case GIT_OBJECT_TREE: { char *buf = NULL; size_t path_len, buf_len; const char *entry_name; const char *sep; git_tree *sub_tree = NULL; error = git_tree_lookup( &sub_tree, data->repository, git_tree_entry_id(entry)); if (error) return error; entry_name = git_tree_entry_name(entry); path_len = strlen(path); buf_len = path_len + strlen(entry_name) + 2; buf = malloc(buf_len); if (!buf) { git_tree_free(sub_tree); giterr_set_oom(); return GIT_ERROR_NOMEMORY; } if (path_len) { sep = "/"; } else { sep = ""; } error = snprintf(buf, buf_len, "%s%s%s", path, sep, entry_name); if (0 <= error && (size_t)error < buf_len) { error = git2r_odb_tree_blobs( sub_tree, buf, commit, author, when, data); } else { giterr_set_str(GIT_ERROR_OS, "Failed to snprintf tree path."); error = GIT_ERROR_OS; } free(buf); git_tree_free(sub_tree); if (error) return error; break; } case GIT_OBJECT_BLOB: if (!Rf_isNull(data->list)) { error = git2r_odb_add_blob( entry, data->odb, data->list, data->n, path, commit, author, when); if (error) return error; } data->n += 1; break; default: break; } } return GIT_OK; } /** * Callback when iterating over blobs * * @param oid Oid of the object * @param payload Payload data * @return int 0 or error code */ static int git2r_odb_blobs_cb( const git_oid *oid, void *payload) { int error = GIT_OK; size_t len; git_object_t type; git2r_odb_blobs_cb_data *p = (git2r_odb_blobs_cb_data*)payload; error = git_odb_read_header(&len, &type, p->odb, oid); if (error) return error; if (type == GIT_OBJECT_COMMIT) { const git_signature *author; git_commit *commit = NULL; git_tree *tree = NULL; char sha[GIT_OID_HEXSZ + 1]; error = git_commit_lookup(&commit, p->repository, oid); if (error) goto cleanup; error = git_commit_tree(&tree, commit); if (error) goto cleanup; git_oid_fmt(sha, oid); sha[GIT_OID_HEXSZ] = '\0'; author = git_commit_author(commit); /* Recursively iterate over all tree's */ error = git2r_odb_tree_blobs( tree, "", sha, author->name, (double)(author->when.time), p); cleanup: git_commit_free(commit); git_tree_free(tree); } return error; } /** * List all blobs available in the database * * List all blobs reachable from the commits in the object * database. First list all commits. Then iterate over each blob from * the tree and sub-trees of each commit. * @param repo S3 class git_repository * @return A list with blob entries */ SEXP attribute_hidden git2r_odb_blobs( SEXP repo) { const char *names[] = {"sha", "path", "name", "len", "commit", "author", "when", ""}; int i, error, nprotect = 0; SEXP result = R_NilValue; git2r_odb_blobs_cb_data cb_data = {0, R_NilValue, NULL, NULL}; git_odb *odb = NULL; git_repository *repository = NULL; repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_repository_odb(&odb, repository); if (error) goto cleanup; cb_data.odb = odb; /* Count number of blobs before creating the list */ cb_data.repository = repository; error = git_odb_foreach(odb, &git2r_odb_blobs_cb, &cb_data); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, names)); nprotect++; i = 0; SET_VECTOR_ELT(result, i++, Rf_allocVector(STRSXP, cb_data.n)); SET_VECTOR_ELT(result, i++, Rf_allocVector(STRSXP, cb_data.n)); SET_VECTOR_ELT(result, i++, Rf_allocVector(STRSXP, cb_data.n)); SET_VECTOR_ELT(result, i++, Rf_allocVector(INTSXP, cb_data.n)); SET_VECTOR_ELT(result, i++, Rf_allocVector(STRSXP, cb_data.n)); SET_VECTOR_ELT(result, i++, Rf_allocVector(STRSXP, cb_data.n)); SET_VECTOR_ELT(result, i, Rf_allocVector(REALSXP, cb_data.n)); cb_data.list = result; cb_data.n = 0; error = git_odb_foreach(odb, &git2r_odb_blobs_cb, &cb_data); cleanup: git_repository_free(repository); git_odb_free(odb); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } git2r/src/git2r_blame.h0000644000176200001440000000162714704013324014434 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_blame_h #define INCLUDE_git2r_blame_h #include #include SEXP git2r_blame_file(SEXP repo, SEXP path); #endif git2r/src/git2r_commit.c0000644000176200001440000003461714700530616014650 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_commit.h" #include "git2r_error.h" #include "git2r_oid.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_signature.h" #include "git2r_tree.h" /** * Check for any changes in index * * @param repository The repository * @return 0 if ok, else error code. */ static int git2r_any_changes_in_index( git_repository *repository) { int error; int changes_in_index = 0; size_t i, count; git_status_list *status = NULL; git_status_options opts = GIT_STATUS_OPTIONS_INIT; opts.show = GIT_STATUS_SHOW_INDEX_ONLY; error = git_status_list_new(&status, repository, &opts); if (error) goto cleanup; count = git_status_list_entrycount(status); for (i = 0; i < count; ++i) { const git_status_entry *s = git_status_byindex(status, i); if (s->status == GIT_STATUS_CURRENT) continue; if (s->status & GIT_STATUS_INDEX_NEW) changes_in_index = 1; else if (s->status & GIT_STATUS_INDEX_MODIFIED) changes_in_index = 1; else if (s->status & GIT_STATUS_INDEX_DELETED) changes_in_index = 1; else if (s->status & GIT_STATUS_INDEX_RENAMED) changes_in_index = 1; else if (s->status & GIT_STATUS_INDEX_TYPECHANGE) changes_in_index = 1; if (changes_in_index) break; } if (!changes_in_index) { giterr_set_str(GIT_ERROR_NONE, git2r_err_nothing_added_to_commit); error = GIT_ERROR; } cleanup: git_status_list_free(status); return error; } /** * Close the commits in parents and free memory of parents. * * @param parents The parent vector of commits. * @param n_parents The number of parents. * @return void */ static void git2r_parents_free( git_commit **parents, size_t n_parents) { if (parents) { size_t i; for (i = 0; i < n_parents; i++) { if (parents[i]) git_commit_free(parents[i]); } free(parents); } } /** * Data structure to hold information when iterating over MERGE_HEAD * entries. */ typedef struct { size_t n; git_repository *repository; git_commit **parents; } git2r_merge_head_cb_data; /** * Invoked 'callback' for each ID in the MERGE_HEAD file. * * @param oid The id of the merge head * @param payload Payload data passed to 'git_repository_mergehead_foreach' * @return 0 */ static int git2r_repository_mergehead_foreach_cb( const git_oid *oid, void *payload) { int error = 0; git2r_merge_head_cb_data *cb_data = (git2r_merge_head_cb_data*)payload; if (cb_data->parents) error = git_commit_lookup( &(cb_data->parents[cb_data->n]), cb_data->repository, oid); cb_data->n += 1; return error; } /** * Retrieve parents of the commit under construction * * @param parents The vector of parents to create and populate. * @param n_parents The length of parents vector * @param repository The repository * @return 0 on succes, or error code */ static int git2r_retrieve_parents( git_commit ***parents, size_t *n_parents, git_repository *repository) { int error; git_oid oid; git2r_merge_head_cb_data cb_data = {0, NULL, NULL}; git_repository_state_t state; error = git_repository_head_unborn(repository); if (1 == error) { *n_parents = 0; return GIT_OK; } else if (0 != error) { return error; } state = git_repository_state(repository); if (state == GIT_REPOSITORY_STATE_MERGE) { /* Count number of merge heads */ error = git_repository_mergehead_foreach( repository, git2r_repository_mergehead_foreach_cb, &cb_data); if (error) return error; } *parents = calloc(cb_data.n + 1, sizeof(git_commit*)); if (!parents) { giterr_set_str(GIT_ERROR_NONE, git2r_err_alloc_memory_buffer); return GIT_ERROR; } *n_parents = cb_data.n + 1; error = git_reference_name_to_id(&oid, repository, "HEAD"); if (error) return error; error = git_commit_lookup(&**parents, repository, &oid); if (error) return error; if (state == GIT_REPOSITORY_STATE_MERGE) { /* Append merge heads to parents */ cb_data.n = 0; cb_data.repository = repository; cb_data.parents = *parents + 1; error = git_repository_mergehead_foreach( repository, git2r_repository_mergehead_foreach_cb, &cb_data); if (error) return error; } return GIT_OK; } /** * Create a commit * * @param out The oid of the newly created commit * @param repository The repository * @param index The index * @param message The commit message * @param author Who is the author of the commit * @param committer Who is the committer * @return 0 on success, or error code */ int attribute_hidden git2r_commit_create( git_oid *out, git_repository *repository, git_index *index, const char *message, git_signature *author, git_signature *committer) { int error; git_oid oid; git_tree *tree = NULL; git_commit **parents = NULL; size_t n_parents = 0; error = git_index_write_tree(&oid, index); if (error) goto cleanup; error = git_tree_lookup(&tree, repository, &oid); if (error) goto cleanup; error = git2r_retrieve_parents(&parents, &n_parents, repository); if (error) goto cleanup; error = git_commit_create( out, repository, "HEAD", author, committer, NULL, message, tree, n_parents, #if LIBGIT2_VER_MAJOR == 1 && \ LIBGIT2_VER_MINOR == 8 && \ (LIBGIT2_VER_REVISION == 0 || LIBGIT2_VER_REVISION == 1) (git_commit*const*)parents); #else (const git_commit**)parents); #endif if (error) goto cleanup; error = git_repository_state_cleanup(repository); cleanup: git2r_parents_free(parents, n_parents); git_tree_free(tree); return error; } /** * Commit * * @param repo S3 class git_repository * @param message The message for the commit * @param author S3 class git_signature * @param committer S3 class git_signature * @return S3 class git_commit */ SEXP attribute_hidden git2r_commit( SEXP repo, SEXP message, SEXP author, SEXP committer) { int error, nprotect = 0; SEXP result = R_NilValue; git_signature *c_author = NULL; git_signature *c_committer = NULL; git_index *index = NULL; git_oid oid; git_repository *repository = NULL; git_commit *commit = NULL; if (git2r_arg_check_string(message)) git2r_error(__func__, NULL, "'message'", git2r_err_string_arg); if (git2r_arg_check_signature(author)) git2r_error(__func__, NULL, "'author'", git2r_err_signature_arg); if (git2r_arg_check_signature(committer)) git2r_error(__func__, NULL, "'committer'", git2r_err_signature_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git2r_signature_from_arg(&c_author, author); if (error) goto cleanup; error = git2r_signature_from_arg(&c_committer, committer); if (error) goto cleanup; error = git2r_any_changes_in_index(repository); if (error) goto cleanup; error = git_repository_index(&index, repository); if (error) goto cleanup; error = git2r_commit_create( &oid, repository, index, CHAR(STRING_ELT(message, 0)), c_author, c_committer); if (error) goto cleanup; error = git_commit_lookup(&commit, repository, &oid); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_commit)); git2r_commit_init(commit, repo, result); cleanup: git_signature_free(c_author); git_signature_free(c_committer); git_index_free(index); git_repository_free(repository); git_commit_free(commit); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Get commit object from S3 class git_commit * * @param out Pointer to the looked up commit * @param repository The repository * @param commit S3 class git_commit * @return 0 or an error code */ int attribute_hidden git2r_commit_lookup( git_commit **out, git_repository *repository, SEXP commit) { SEXP sha; git_oid oid; sha = git2r_get_list_element(commit, "sha"); git_oid_fromstr(&oid, CHAR(STRING_ELT(sha, 0))); return git_commit_lookup(out, repository, &oid); } /** * Get the tree pointed to by a commit * * @param commit S3 class git_commit or git_stash * @return S3 class git_tree */ SEXP attribute_hidden git2r_commit_tree( SEXP commit) { int error, nprotect = 0; SEXP result = R_NilValue; SEXP repo; git_commit *commit_obj = NULL; git_repository *repository = NULL; git_tree *tree = NULL; if (git2r_arg_check_commit_stash(commit)) git2r_error(__func__, NULL, "'commit'", git2r_err_commit_stash_arg); repo = git2r_get_list_element(commit, "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git2r_commit_lookup(&commit_obj, repository, commit); if (error) goto cleanup; error = git_commit_tree(&tree, commit_obj); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_tree)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_tree)); git2r_tree_init((git_tree*)tree, repo, result); cleanup: git_commit_free(commit_obj); git_tree_free(tree); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Init slots in S3 class git_commit * * @param source a commit object * @param repo S3 class git_repository that contains the blob * @param dest S3 class git_commit to initialize * @return void */ void attribute_hidden git2r_commit_init( git_commit *source, SEXP repo, SEXP dest) { const char *str; const git_signature *signature; char sha[GIT_OID_HEXSZ + 1]; git_oid_fmt(sha, git_commit_id(source)); sha[GIT_OID_HEXSZ] = '\0'; SET_VECTOR_ELT(dest, git2r_S3_item__git_commit__sha, Rf_mkString(sha)); signature = git_commit_author(source); if (signature) { SEXP elem = VECTOR_ELT(dest, git2r_S3_item__git_commit__author); if (Rf_isNull(elem)) { SET_VECTOR_ELT( dest, git2r_S3_item__git_commit__author, elem = Rf_mkNamed(VECSXP, git2r_S3_items__git_signature)); Rf_setAttrib(elem, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_signature)); } git2r_signature_init(signature, elem); } signature = git_commit_committer(source); if (signature) { SEXP elem = VECTOR_ELT(dest, git2r_S3_item__git_commit__committer); if (Rf_isNull(elem)) { SET_VECTOR_ELT( dest, git2r_S3_item__git_commit__author, elem = Rf_mkNamed(VECSXP, git2r_S3_items__git_signature)); Rf_setAttrib(elem, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_signature)); } git2r_signature_init(signature, elem); } str = git_commit_summary(source); if (str) SET_VECTOR_ELT(dest, git2r_S3_item__git_commit__summary, Rf_mkString(str)); str = git_commit_message(source); if (str) SET_VECTOR_ELT(dest, git2r_S3_item__git_commit__message, Rf_mkString(str)); SET_VECTOR_ELT(dest, git2r_S3_item__git_commit__repo, Rf_duplicate(repo)); } /** * Parents of a commit * * @param commit S3 class git_commit * @return list of S3 class git_commit objects */ SEXP attribute_hidden git2r_commit_parent_list( SEXP commit) { int error, nprotect = 0; size_t i, n; SEXP repo; SEXP list = R_NilValue; git_commit *commit_obj = NULL; git_repository *repository = NULL; if (git2r_arg_check_commit(commit)) git2r_error(__func__, NULL, "'commit'", git2r_err_commit_arg); repo = git2r_get_list_element(commit, "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git2r_commit_lookup(&commit_obj, repository, commit); if (error) goto cleanup; n = git_commit_parentcount(commit_obj); PROTECT(list = Rf_allocVector(VECSXP, n)); nprotect++; for (i = 0; i < n; i++) { git_commit *parent = NULL; SEXP item; error = git_commit_parent(&parent, commit_obj, i); if (error) goto cleanup; SET_VECTOR_ELT( list, i, item = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); Rf_setAttrib(item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_commit)); git2r_commit_init(parent, repo, item); git_commit_free(parent); } cleanup: git_commit_free(commit_obj); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return list; } git2r/src/git2r_reset.c0000644000176200001440000000726614700265032014477 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_commit.h" #include "git2r_error.h" #include "git2r_repository.h" #include "git2r_reset.h" #include "git2r_S3.h" #include "git2r_signature.h" /** * Reset current HEAD to the specified state * * @param commit The commit to which the HEAD should be moved to. * @param reset_type Kind of reset operation to perform. 'soft' means * the Head will be moved to the commit. 'mixed' reset will trigger a * 'soft' reset, plus the index will be replaced with the content of * the commit tree. 'hard' reset will trigger a 'mixed' reset and the * working directory will be replaced with the content of the index. * @return R_NilValue */ SEXP attribute_hidden git2r_reset( SEXP commit, SEXP reset_type) { int error; SEXP repo; git_commit *target = NULL; git_repository *repository = NULL; if (git2r_arg_check_commit(commit)) git2r_error(__func__, NULL, "'commit'", git2r_err_commit_arg); if (git2r_arg_check_integer(reset_type)) git2r_error(__func__, NULL, "'reset_type'", git2r_err_integer_arg); repo = git2r_get_list_element(commit, "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git2r_commit_lookup(&target, repository, commit); if (error) goto cleanup; error = git_reset( repository, (git_object*)target, INTEGER(reset_type)[0], NULL); cleanup: git_commit_free(target); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Updates some entries in the index from the HEAD commit tree. * * @param repo S3 class git_repository * @param path The paths to reset * @return R_NilValue */ SEXP attribute_hidden git2r_reset_default( SEXP repo, SEXP path) { int error = 0; git_strarray pathspec = {0}; git_reference *head = NULL; git_object *head_commit = NULL; git_repository *repository = NULL; if (git2r_arg_check_string_vec(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_vec_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git2r_copy_string_vec(&pathspec, path); if (error || !pathspec.count) goto cleanup; error = git_repository_head(&head, repository); if (error) goto cleanup; error = git_reference_peel(&head_commit, head, GIT_OBJECT_COMMIT); if (error) goto cleanup; error = git_reset_default(repository, head_commit, &pathspec); cleanup: git_reference_free(head); git_object_free(head_commit); free(pathspec.strings); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } git2r/src/Makevars.win0000644000176200001440000000037414700260351014362 0ustar liggesusersPKG_CPPFLAGS = -DR_NO_REMAP -DSTRICT_R_HEADERS PKG_LIBS = \ -lgit2 -lpcre -lssh2 -lz -lssl -lcrypto -lgcrypt -lgpg-error \ -lwinhttp -lws2_32 -lcrypt32 -lole32 -lrpcrt4 all: clean clean: rm -f $(SHLIB) $(OBJECTS) .PHONY: all clean git2r/src/git2r_branch.h0000644000176200001440000000311313273077667014625 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_branch_h #define INCLUDE_git2r_branch_h #include #include #include SEXP git2r_branch_canonical_name(SEXP branch); SEXP git2r_branch_create(SEXP branch_name, SEXP commit, SEXP force); SEXP git2r_branch_delete(SEXP branch); int git2r_branch_init( const git_reference *source, git_branch_t type, SEXP repo, SEXP dest); SEXP git2r_branch_is_head(SEXP branch); SEXP git2r_branch_list(SEXP repo, SEXP flags); SEXP git2r_branch_remote_name(SEXP branch); SEXP git2r_branch_remote_url(SEXP branch); SEXP git2r_branch_rename(SEXP branch, SEXP new_branch_name, SEXP force); SEXP git2r_branch_target(SEXP branch); SEXP git2r_branch_get_upstream(SEXP branch); SEXP git2r_branch_set_upstream(SEXP branch, SEXP upstream_name); SEXP git2r_branch_upstream_canonical_name(SEXP branch); #endif git2r/src/git2r_libgit2.c0000644000176200001440000000622314700262225014702 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_error.h" #include "git2r_libgit2.h" /** * Return compile time options for libgit2. * * @return A VECSXP with threads, https and ssh set to TRUE/FALSE */ SEXP attribute_hidden git2r_libgit2_features(void) { const char *names[] = {"threads", "https", "ssh", ""}; int value = git_libgit2_features(); SEXP features; PROTECT(features = Rf_mkNamed(VECSXP, names)); SET_VECTOR_ELT(features, 0, Rf_ScalarLogical(value & GIT_FEATURE_THREADS)); SET_VECTOR_ELT(features, 1, Rf_ScalarLogical(value & GIT_FEATURE_HTTPS)); SET_VECTOR_ELT(features, 2, Rf_ScalarLogical(value & GIT_FEATURE_SSH)); UNPROTECT(1); return features; } /** * Return the version of the libgit2 library being currently used. * * @return A VECSXP with major, minor and rev. */ SEXP attribute_hidden git2r_libgit2_version(void) { const char *names[] = {"major", "minor", "rev", ""}; SEXP version; int major, minor, rev; git_libgit2_version(&major, &minor, &rev); PROTECT(version = Rf_mkNamed(VECSXP, names)); SET_VECTOR_ELT(version, 0, Rf_ScalarInteger(major)); SET_VECTOR_ELT(version, 1, Rf_ScalarInteger(minor)); SET_VECTOR_ELT(version, 2, Rf_ScalarInteger(rev)); UNPROTECT(1); return version; } /** * Set the SSL certificate-authority locations * * Either parameter may be 'NULL', but not both. * @param filename Location of a file containing several certificates * concatenated together. Default NULL. * @param path Location of a directory holding several certificates, * one per file. Default NULL. * @return NULL */ SEXP attribute_hidden git2r_ssl_cert_locations( SEXP filename, SEXP path) { const char *f = NULL; const char *p = NULL; if (!Rf_isNull(filename)) { if (git2r_arg_check_string(filename)) git2r_error(__func__, NULL, "'filename'", git2r_err_string_arg); f = CHAR(STRING_ELT(filename, 0)); } if (!Rf_isNull(path)) { if (git2r_arg_check_string(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_arg); p = CHAR(STRING_ELT(path, 0)); } if (f == NULL && p == NULL) git2r_error(__func__, NULL, git2r_err_ssl_cert_locations, NULL); if (git_libgit2_opts(GIT_OPT_SET_SSL_CERT_LOCATIONS, f, p)) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } git2r/src/git2r_tree.h0000644000176200001440000000176013273077667014335 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2018 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_tree_h #define INCLUDE_git2r_tree_h #include #include #include void git2r_tree_init(const git_tree *source, SEXP repo, SEXP dest); SEXP git2r_tree_walk(SEXP tree, SEXP recursive); #endif git2r/src/git2r_repository.h0000644000176200001440000000277514530613147015606 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_repository_h #define INCLUDE_git2r_repository_h #include #include #include git_repository* git2r_repository_open(SEXP repo); SEXP git2r_repository_can_open(SEXP path); SEXP git2r_repository_discover(SEXP path, SEXP ceiling); SEXP git2r_repository_fetch_heads(SEXP repo); SEXP git2r_repository_head(SEXP repo); SEXP git2r_repository_head_detached(SEXP repo); SEXP git2r_repository_init(SEXP path, SEXP bare, SEXP branch); SEXP git2r_repository_is_bare(SEXP repo); SEXP git2r_repository_is_empty(SEXP repo); SEXP git2r_repository_is_shallow(SEXP repo); SEXP git2r_repository_set_head(SEXP repo, SEXP ref_name); SEXP git2r_repository_set_head_detached(SEXP commit); SEXP git2r_repository_workdir(SEXP repo); #endif git2r/src/git2r_signature.c0000644000176200001440000000714314700265111015346 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "git2r_error.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_signature.h" /** * Get the configured signature for a repository * * @param repo S3 class git_repository * @return S3 class git_signature */ SEXP attribute_hidden git2r_signature_default( SEXP repo) { int error, nprotect = 0; git_repository *repository = NULL; git_signature *signature = NULL; SEXP result = R_NilValue; repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_signature_default(&signature, repository); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_signature)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_signature)); git2r_signature_init(signature, result); cleanup: git_repository_free(repository); git_signature_free(signature); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Init signature from SEXP signature argument * * @param out new signature * @param signature SEXP argument with S3 class git_signature * @return 0 or an error code */ int attribute_hidden git2r_signature_from_arg( git_signature **out, SEXP signature) { SEXP when = git2r_get_list_element(signature, "when"); return git_signature_new( out, CHAR(STRING_ELT(git2r_get_list_element(signature, "name"), 0)), CHAR(STRING_ELT(git2r_get_list_element(signature, "email"), 0)), REAL(git2r_get_list_element(when, "time"))[0], REAL(git2r_get_list_element(when, "offset"))[0]); } /** * Init slots in S3 class git_signature. * * @param source A git signature * @param dest S3 class git_signature to initialize * @return void */ void attribute_hidden git2r_signature_init( const git_signature *source, SEXP dest) { SEXP when; SET_VECTOR_ELT( dest, git2r_S3_item__git_signature__name, Rf_mkString(source->name)); SET_VECTOR_ELT( dest, git2r_S3_item__git_signature__email, Rf_mkString(source->email)); when = VECTOR_ELT(dest, git2r_S3_item__git_signature__when); if (Rf_isNull(when)) { SET_VECTOR_ELT( dest, git2r_S3_item__git_signature__when, when = Rf_mkNamed(VECSXP, git2r_S3_items__git_time)); Rf_setAttrib(when, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_time)); } SET_VECTOR_ELT( when, git2r_S3_item__git_time__time, Rf_ScalarReal((double)source->when.time)); SET_VECTOR_ELT( when, git2r_S3_item__git_time__offset, Rf_ScalarReal((double)source->when.offset)); } git2r/src/git2r_clone.c0000644000176200001440000001150414700263162014445 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_clone.h" #include "git2r_cred.h" #include "git2r_error.h" #include "git2r_transfer.h" /** * Show progress of clone * * @param progress The clone progress data * @param payload A pointer to a git2r_clone_data data * structure * @return 0 */ static int git2r_clone_progress( const git_indexer_progress *progress, void *payload) { int kbytes = progress->received_bytes / 1024; git2r_transfer_data *pd = (git2r_transfer_data*)payload; if (progress->received_objects < progress->total_objects) { int received_percent = (100 * progress->received_objects) / progress->total_objects; if (received_percent > pd->received_progress) { Rprintf("Receiving objects: % 3i%% (%i/%i), %4d kb\n", received_percent, progress->received_objects, progress->total_objects, kbytes); pd->received_progress += 10; } } else if (!pd->received_done) { Rprintf("Receiving objects: 100%% (%i/%i), %4d kb, done.\n", progress->received_objects, progress->total_objects, kbytes); pd->received_done = 1; } return 0; } /** * Clone a remote repository * * @param url the remote repository to clone * @param local_path local directory to clone to * @param bare Create a bare repository. * @param branch The name of the branch to checkout. Default is NULL * which means to use the remote's default branch. * @param checkout Checkout HEAD after the clone is complete. * @param credentials The credentials for remote repository access. * @param progress show progress * @return R_NilValue */ SEXP attribute_hidden git2r_clone( SEXP url, SEXP local_path, SEXP bare, SEXP branch, SEXP checkout, SEXP credentials, SEXP progress) { int error; git_repository *repository = NULL; git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git2r_transfer_data payload = GIT2R_TRANSFER_DATA_INIT; if (git2r_arg_check_string(url)) git2r_error(__func__, NULL, "'url'", git2r_err_string_arg); if (git2r_arg_check_string(local_path)) git2r_error(__func__, NULL, "'local_path'", git2r_err_string_arg); if (git2r_arg_check_logical(bare)) git2r_error(__func__, NULL, "'bare'", git2r_err_logical_arg); if ((!Rf_isNull(branch)) && git2r_arg_check_string(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_string_arg); if (git2r_arg_check_logical(checkout)) git2r_error(__func__, NULL, "'checkout'", git2r_err_logical_arg); if (git2r_arg_check_credentials(credentials)) git2r_error(__func__, NULL, "'credentials'", git2r_err_credentials_arg); if (git2r_arg_check_logical(progress)) git2r_error(__func__, NULL, "'progress'", git2r_err_logical_arg); if (LOGICAL(checkout)[0]) checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; else checkout_opts.checkout_strategy = GIT_CHECKOUT_NONE; clone_opts.checkout_opts = checkout_opts; payload.credentials = credentials; clone_opts.fetch_opts.callbacks.payload = &payload; clone_opts.fetch_opts.callbacks.credentials = &git2r_cred_acquire_cb; if (LOGICAL(bare)[0]) clone_opts.bare = 1; if (!Rf_isNull(branch)) clone_opts.checkout_branch = CHAR(STRING_ELT(branch, 0)); if (LOGICAL(progress)[0]) { clone_opts.fetch_opts.callbacks.transfer_progress = &git2r_clone_progress; Rprintf("cloning into '%s'...\n", CHAR(STRING_ELT(local_path, 0))); } error = git_clone(&repository, CHAR(STRING_ELT(url, 0)), CHAR(STRING_ELT(local_path, 0)), &clone_opts); git_repository_free(repository); if (error) git2r_error( __func__, git_error_last(), git2r_err_unable_to_authenticate, NULL); return R_NilValue; } git2r/src/git2r_stash.h0000644000176200001440000000222413316243475014502 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2018 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_stash_h #define INCLUDE_git2r_stash_h #include #include SEXP git2r_stash_apply(SEXP repo, SEXP index); SEXP git2r_stash_drop(SEXP repo, SEXP index); SEXP git2r_stash_pop(SEXP repo, SEXP index); SEXP git2r_stash_save(SEXP repo, SEXP message, SEXP index, SEXP untracked, SEXP ignored, SEXP stasher); SEXP git2r_stash_list(SEXP repo); #endif git2r/src/git2r_libgit2.h0000644000176200001440000000175413137360640014716 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_libgit2_h #define INCLUDE_git2r_libgit2_h #include #include SEXP git2r_libgit2_features(void); SEXP git2r_libgit2_version(void); SEXP git2r_ssl_cert_locations(SEXP filename, SEXP path); #endif git2r/src/git2r_blob.h0000644000176200001440000000226014530613147014272 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2023 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_blob_h #define INCLUDE_git2r_blob_h #include #include #include SEXP git2r_blob_content(SEXP blob, SEXP raw); SEXP git2r_blob_create_fromdisk(SEXP repo, SEXP path); SEXP git2r_blob_create_fromworkdir(SEXP repo, SEXP relative_path); void git2r_blob_init(const git_blob *source, SEXP repo, SEXP dest); SEXP git2r_blob_is_binary(SEXP blob); SEXP git2r_blob_rawsize(SEXP blob); #endif git2r/src/git2r_blob.c0000644000176200001440000002235114700263045014265 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "git2r_arg.h" #include "git2r_blob.h" #include "git2r_error.h" #include "git2r_repository.h" #include "git2r_S3.h" /** * Get content of a blob * * @param blob S3 class git_blob * @param raw If true, return content as a RAWSXP vector, else as a * STRSXP vector. * @return content */ SEXP attribute_hidden git2r_blob_content( SEXP blob, SEXP raw) { int error, nprotect = 0; SEXP result = R_NilValue; SEXP sha; git_blob *blob_obj = NULL; git_oid oid; git_repository *repository = NULL; if (git2r_arg_check_blob(blob)) git2r_error(__func__, NULL, "'blob'", git2r_err_blob_arg); if (git2r_arg_check_logical(raw)) git2r_error(__func__, NULL, "'raw'", git2r_err_logical_arg); repository = git2r_repository_open(git2r_get_list_element(blob, "repo")); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); sha = git2r_get_list_element(blob, "sha"); git_oid_fromstr(&oid, CHAR(STRING_ELT(sha, 0))); error = git_blob_lookup(&blob_obj, repository, &oid); if (error) goto cleanup; if (LOGICAL(raw)[0]) { PROTECT(result = Rf_allocVector(RAWSXP, git_blob_rawsize(blob_obj))); nprotect++; memcpy( RAW(result), git_blob_rawcontent(blob_obj), git_blob_rawsize(blob_obj)); } else { PROTECT(result = Rf_allocVector(STRSXP, 1)); nprotect++; if (git_blob_is_binary(blob_obj)) { SET_STRING_ELT(result, 0, NA_STRING); } else { SET_STRING_ELT(result, 0, Rf_mkChar(git_blob_rawcontent(blob_obj))); } } cleanup: git_blob_free(blob_obj); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Read a file from the filesystem and write its content to the * Object Database as a loose blob * @param repo The repository where the blob will be written. Can be * a bare repository. * @param path The file from which the blob will be created. * @return list of S3 class git_blob objects */ SEXP attribute_hidden git2r_blob_create_fromdisk( SEXP repo, SEXP path) { SEXP result = R_NilValue; int error = 0, nprotect = 0; size_t len, i; git_repository *repository = NULL; if (git2r_arg_check_string_vec(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_vec_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); len = Rf_length(path); PROTECT(result = Rf_allocVector(VECSXP, len)); nprotect++; for (i = 0; i < len; i++) { if (NA_STRING != STRING_ELT(path, i)) { git_oid oid; git_blob *blob = NULL; SEXP item; error = git_blob_create_from_disk( &oid, repository, CHAR(STRING_ELT(path, i))); if (error) goto cleanup; error = git_blob_lookup(&blob, repository, &oid); if (error) goto cleanup; SET_VECTOR_ELT(result, i, item = Rf_mkNamed(VECSXP, git2r_S3_items__git_blob)); Rf_setAttrib(item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_blob)); git2r_blob_init(blob, repo, item); git_blob_free(blob); } } cleanup: git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Create blob from file in working directory * * Read a file from the working folder of a repository and write its * content to the Object Database as a loose blob. The method is * vectorized and accepts a vector of files to create blobs from. * @param repo The repository where the blob(s) will be * written. Cannot be a bare repository. * @param relative_path The file(s) from which the blob will be * created, relative to the repository's working dir. * @return list of S3 class git_blob objects */ SEXP attribute_hidden git2r_blob_create_fromworkdir( SEXP repo, SEXP relative_path) { SEXP result = R_NilValue; int error = 0, nprotect = 0; size_t len, i; git_repository *repository = NULL; if (git2r_arg_check_string_vec(relative_path)) git2r_error(__func__, NULL, "'relative_path'", git2r_err_string_vec_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); len = Rf_length(relative_path); PROTECT(result = Rf_allocVector(VECSXP, len)); nprotect++; for (i = 0; i < len; i++) { if (NA_STRING != STRING_ELT(relative_path, i)) { git_oid oid; git_blob *blob = NULL; SEXP item; error = git_blob_create_from_workdir( &oid, repository, CHAR(STRING_ELT(relative_path, i))); if (error) goto cleanup; error = git_blob_lookup(&blob, repository, &oid); if (error) goto cleanup; SET_VECTOR_ELT(result, i, item = Rf_mkNamed(VECSXP, git2r_S3_items__git_blob)); Rf_setAttrib(item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_blob)); git2r_blob_init(blob, repo, item); git_blob_free(blob); } } cleanup: git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Init entries in a S3 class git_blob * * @param source a blob * @param repo S3 class git_repository that contains the blob * @param dest S3 class git_blob to initialize * @return void */ void attribute_hidden git2r_blob_init( const git_blob *source, SEXP repo, SEXP dest) { const git_oid *oid; char sha[GIT_OID_HEXSZ + 1]; oid = git_blob_id(source); git_oid_tostr(sha, sizeof(sha), oid); SET_VECTOR_ELT(dest, git2r_S3_item__git_blob__sha, Rf_mkString(sha)); SET_VECTOR_ELT(dest, git2r_S3_item__git_blob__repo, Rf_duplicate(repo)); } /** * Is blob binary * * @param blob S3 class git_blob * @return TRUE if binary data, FALSE if not */ SEXP attribute_hidden git2r_blob_is_binary( SEXP blob) { int error, nprotect = 0; SEXP result = R_NilValue; SEXP sha; git_blob *blob_obj = NULL; git_oid oid; git_repository *repository = NULL; if (git2r_arg_check_blob(blob)) git2r_error(__func__, NULL, "'blob'", git2r_err_blob_arg); repository = git2r_repository_open(git2r_get_list_element(blob, "repo")); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); sha = git2r_get_list_element(blob, "sha"); git_oid_fromstr(&oid, CHAR(STRING_ELT(sha, 0))); error = git_blob_lookup(&blob_obj, repository, &oid); if (error) goto cleanup; PROTECT(result = Rf_allocVector(LGLSXP, 1)); nprotect++; if (git_blob_is_binary(blob_obj)) LOGICAL(result)[0] = 1; else LOGICAL(result)[0] = 0; cleanup: git_blob_free(blob_obj); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Size in bytes of contents of a blob * * @param blob S3 class git_blob * @return size */ SEXP attribute_hidden git2r_blob_rawsize( SEXP blob) { int error; SEXP sha; git_off_t size = 0; git_blob *blob_obj = NULL; git_oid oid; git_repository *repository = NULL; if (git2r_arg_check_blob(blob)) git2r_error(__func__, NULL, "'blob'", git2r_err_blob_arg); repository = git2r_repository_open(git2r_get_list_element(blob, "repo")); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); sha = git2r_get_list_element(blob, "sha"); git_oid_fromstr(&oid, CHAR(STRING_ELT(sha, 0))); error = git_blob_lookup(&blob_obj, repository, &oid); if (error) goto cleanup; size = git_blob_rawsize(blob_obj); cleanup: git_blob_free(blob_obj); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return Rf_ScalarInteger(size); } git2r/src/git2r_error.h0000644000176200001440000000512414700530233014500 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_error_h #define INCLUDE_git2r_error_h #include /** * Error messages */ extern const char git2r_err_alloc_memory_buffer[]; extern const char git2r_err_branch_not_local[]; extern const char git2r_err_branch_not_remote[]; extern const char git2r_err_checkout_tree[]; extern const char git2r_err_invalid_refname[]; extern const char git2r_err_invalid_remote[]; extern const char git2r_err_invalid_repository[]; extern const char git2r_err_nothing_added_to_commit[]; extern const char git2r_err_object_type[]; extern const char git2r_err_reference[]; extern const char git2r_err_repo_init[]; extern const char git2r_err_revparse_not_found[]; extern const char git2r_err_revparse_single[]; extern const char git2r_err_ssl_cert_locations[]; extern const char git2r_err_unexpected_config_level[]; extern const char git2r_err_unable_to_authenticate[]; /** * Error messages specific to argument checking */ extern const char git2r_err_blob_arg[]; extern const char git2r_err_branch_arg[]; extern const char git2r_err_commit_arg[]; extern const char git2r_err_commit_stash_arg[]; extern const char git2r_err_credentials_arg[]; extern const char git2r_err_diff_arg[]; extern const char git2r_err_fetch_heads_arg[]; extern const char git2r_err_filename_arg[]; extern const char git2r_err_sha_arg[]; extern const char git2r_err_integer_arg[]; extern const char git2r_err_integer_gte_zero_arg[]; extern const char git2r_err_list_arg[]; extern const char git2r_err_logical_arg[]; extern const char git2r_err_note_arg[]; extern const char git2r_err_signature_arg[]; extern const char git2r_err_string_arg[]; extern const char git2r_err_string_vec_arg[]; extern const char git2r_err_tag_arg[]; extern const char git2r_err_tree_arg[]; void git2r_error( const char *func_name, const git_error *err, const char *msg1, const char *msg2); #endif git2r/src/git2r_graph.h0000644000176200001440000000174013137360640014456 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_graph_h #define INCLUDE_git2r_graph_h #include #include SEXP git2r_graph_ahead_behind(SEXP local, SEXP upstream); SEXP git2r_graph_descendant_of(SEXP commit, SEXP ancestor); #endif git2r/src/git2r_graph.c0000644000176200001440000001065114700262114014444 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_error.h" #include "git2r_oid.h" #include "git2r_repository.h" #include "git2r_S3.h" /** * Count the number of unique commits between two commit objects * * @param local The commit for local * @param upstream The commit for upstream * @return Integer vector of length two with the values ahead and * behind. */ SEXP attribute_hidden git2r_graph_ahead_behind( SEXP local, SEXP upstream) { size_t ahead, behind; int error, nprotect = 0; SEXP result = R_NilValue; SEXP local_repo, local_sha; SEXP upstream_repo, upstream_sha; git_oid local_oid, upstream_oid; git_repository *repository = NULL; if (git2r_arg_check_commit(local)) git2r_error(__func__, NULL, "'local'", git2r_err_commit_arg); if (git2r_arg_check_commit(upstream)) git2r_error(__func__, NULL, "'upstream'", git2r_err_commit_arg); local_repo = git2r_get_list_element(local, "repo"); upstream_repo = git2r_get_list_element(upstream, "repo"); if (git2r_arg_check_same_repo(local_repo, upstream_repo)) git2r_error(__func__, NULL, "'local' and 'upstream' not from same repository", NULL); repository = git2r_repository_open(local_repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); local_sha = git2r_get_list_element(local, "sha"); git2r_oid_from_sha_sexp(local_sha, &local_oid); upstream_sha = git2r_get_list_element(upstream, "sha"); git2r_oid_from_sha_sexp(upstream_sha, &upstream_oid); error = git_graph_ahead_behind(&ahead, &behind, repository, &local_oid, &upstream_oid); if (error) goto cleanup; PROTECT(result = Rf_allocVector(INTSXP, 2)); nprotect++; INTEGER(result)[0] = ahead; INTEGER(result)[1] = behind; cleanup: git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Determine if a commit is the descendant of another commit. * * @param commit A commit. * @param ancestor A potential ancestor commit. * @return TRUE or FALSE */ SEXP attribute_hidden git2r_graph_descendant_of( SEXP commit, SEXP ancestor) { int error, descendant_of = 0; SEXP commit_repo, commit_sha; SEXP ancestor_repo, ancestor_sha; git_oid commit_oid, ancestor_oid; git_repository *repository = NULL; if (git2r_arg_check_commit(commit)) git2r_error(__func__, NULL, "'commit'", git2r_err_commit_arg); if (git2r_arg_check_commit(ancestor)) git2r_error(__func__, NULL, "'ancestor'", git2r_err_commit_arg); commit_repo = git2r_get_list_element(commit, "repo"); ancestor_repo = git2r_get_list_element(ancestor, "repo"); if (git2r_arg_check_same_repo(commit_repo, ancestor_repo)) git2r_error(__func__, NULL, "'commit' and 'ancestor' not from same repository", NULL); repository = git2r_repository_open(commit_repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); commit_sha = git2r_get_list_element(commit, "sha"); git2r_oid_from_sha_sexp(commit_sha, &commit_oid); ancestor_sha = git2r_get_list_element(ancestor, "sha"); git2r_oid_from_sha_sexp(ancestor_sha, &ancestor_oid); error = git_graph_descendant_of(repository, &commit_oid, &ancestor_oid); if (0 > error || 1 < error) goto cleanup; descendant_of = error; error = 0; cleanup: git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return Rf_ScalarLogical(descendant_of); } git2r/src/git2r_cred.h0000644000176200001440000000176414700261470014276 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_cred_h #define INCLUDE_git2r_cred_h #include int git2r_cred_acquire_cb( git_credential **out, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload); #endif git2r/src/git2r_status.c0000644000176200001440000003342514700265147014703 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "git2r_arg.h" #include "git2r_error.h" #include "git2r_repository.h" #include "git2r_status.h" /** * Count number of ignored files * * @param status_list Representation of a status collection * @return The number of files */ static size_t git2r_status_count_ignored( git_status_list *status_list) { size_t i = 0; size_t ignored = 0; size_t count = git_status_list_entrycount(status_list); for (; i < count; ++i) { const git_status_entry *s = git_status_byindex(status_list, i); if (s->status == GIT_STATUS_IGNORED) ignored++; } return ignored; } /** * Count number of changes in index * * @param status_list Representation of a status collection * @return The number of changes */ static size_t git2r_status_count_staged( git_status_list *status_list) { size_t i = 0; size_t changes = 0; size_t count = git_status_list_entrycount(status_list); for (; i < count; ++i) { const git_status_entry *s = git_status_byindex(status_list, i); if (s->status == GIT_STATUS_CURRENT) continue; if (s->status & GIT_STATUS_INDEX_NEW) changes++; else if (s->status & GIT_STATUS_INDEX_MODIFIED) changes++; else if (s->status == GIT_STATUS_INDEX_DELETED) changes++; else if (s->status & GIT_STATUS_INDEX_RENAMED) changes++; else if (s->status & GIT_STATUS_INDEX_TYPECHANGE) changes++; } return changes; } /** * Count number of changes in workdir relative to index * * @param status_list Representation of a status collection * @return The number of changes */ static size_t git2r_status_count_unstaged( git_status_list *status_list) { size_t i = 0; size_t changes = 0; size_t count = git_status_list_entrycount(status_list); for (; i < count; ++i) { const git_status_entry *s = git_status_byindex(status_list, i); if (s->status == GIT_STATUS_CURRENT || s->index_to_workdir == NULL) continue; if (s->status & GIT_STATUS_WT_MODIFIED) changes++; else if (s->status & GIT_STATUS_WT_DELETED) changes++; else if (s->status & GIT_STATUS_WT_RENAMED) changes++; else if (s->status & GIT_STATUS_WT_TYPECHANGE) changes++; else if (s->status == (GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW)) changes++; else if (s->status & GIT_STATUS_CONFLICTED) changes++; } return changes; } /** * Count number of untracked files * * @param status_list Representation of a status collection * @return The number of files */ static size_t git2r_status_count_untracked( git_status_list *status_list) { size_t i = 0; size_t untracked = 0; size_t count = git_status_list_entrycount(status_list); for (; i < count; ++i) { const git_status_entry *s = git_status_byindex(status_list, i); if (s->status == GIT_STATUS_WT_NEW) untracked++; } return untracked; } /** * Add ignored files * * @param list The list to hold the result * @param list_index The index in list where to add the new sub list * with ignored files. * @param status_list Representation of a status collection * @return void */ static void git2r_status_list_ignored( SEXP list, size_t list_index, git_status_list *status_list) { size_t i = 0, j = 0, count; SEXP item, names; /* Create list with the correct number of entries */ count = git2r_status_count_ignored(status_list); SET_VECTOR_ELT(list, list_index, item = Rf_allocVector(VECSXP, count)); Rf_setAttrib(item, R_NamesSymbol, names = Rf_allocVector(STRSXP, count)); /* i index the entrycount. j index the added change in list */ count = git_status_list_entrycount(status_list); for (; i < count; i++) { const git_status_entry *s = git_status_byindex(status_list, i); if (s->status == GIT_STATUS_IGNORED) { SET_STRING_ELT(names, j, Rf_mkChar("ignored")); SET_VECTOR_ELT(item, j, Rf_mkString(s->index_to_workdir->old_file.path)); j++; } } } /** * Add changes in index * * @param list The list to hold the result * @param list_index The index in list where to add the new sub list * with changed files in index. * @param status_list Representation of a status collection * @return void */ static void git2r_status_list_staged( SEXP list, size_t list_index, git_status_list *status_list) { size_t i = 0, j = 0, n; SEXP sub_list, sub_list_names; /* Create list with the correct number of entries */ n = git2r_status_count_staged(status_list); SET_VECTOR_ELT(list, list_index, sub_list = Rf_allocVector(VECSXP, n)); Rf_setAttrib(sub_list, R_NamesSymbol, sub_list_names = Rf_allocVector(STRSXP, n)); /* i index the entrycount. j index the added change in list */ n = git_status_list_entrycount(status_list); for (; i < n; i++) { char *istatus = NULL; const char *old_path, *new_path; const git_status_entry *s = git_status_byindex(status_list, i); if (s->status == GIT_STATUS_CURRENT) continue; if (s->status & GIT_STATUS_INDEX_NEW) istatus = "new"; else if (s->status & GIT_STATUS_INDEX_MODIFIED) istatus = "modified"; else if (s->status == GIT_STATUS_INDEX_DELETED) istatus = "deleted"; else if (s->status & GIT_STATUS_INDEX_RENAMED) istatus = "renamed"; else if (s->status & GIT_STATUS_INDEX_TYPECHANGE) istatus = "typechange"; if (!istatus) continue; SET_STRING_ELT(sub_list_names, j, Rf_mkChar(istatus)); old_path = s->head_to_index->old_file.path; new_path = s->head_to_index->new_file.path; if (old_path && new_path && strcmp(old_path, new_path)) { SEXP item; SET_VECTOR_ELT(sub_list, j, item = Rf_allocVector(STRSXP, 2)); SET_STRING_ELT(item, 0, Rf_mkChar(old_path)); SET_STRING_ELT(item, 1, Rf_mkChar(new_path)); } else { SEXP item; SET_VECTOR_ELT(sub_list, j, item = Rf_allocVector(STRSXP, 1)); SET_STRING_ELT(item, 0, Rf_mkChar(old_path ? old_path : new_path)); } j++; } } /** * Add changes in workdir relative to index * * @param list The list to hold the result * @param list_index The index in list where to add the new sub list * with unstaged files. * @param status_list Representation of a status collection * @return void */ static void git2r_status_list_unstaged( SEXP list, size_t list_index, git_status_list *status_list) { size_t i = 0, j = 0, n; SEXP sub_list, sub_list_names; /* Create list with the correct number of entries */ n = git2r_status_count_unstaged(status_list); SET_VECTOR_ELT(list, list_index, sub_list = Rf_allocVector(VECSXP, n)); Rf_setAttrib(sub_list, R_NamesSymbol, sub_list_names = Rf_allocVector(STRSXP, n)); /* i index the entrycount. j index the added change in list */ n = git_status_list_entrycount(status_list); for (; i < n; i++) { char *wstatus = NULL; const char *old_path, *new_path; const git_status_entry *s = git_status_byindex(status_list, i); if (s->status == GIT_STATUS_CURRENT || s->index_to_workdir == NULL) continue; if (s->status & GIT_STATUS_WT_MODIFIED) wstatus = "modified"; else if (s->status & GIT_STATUS_WT_DELETED) wstatus = "deleted"; else if (s->status & GIT_STATUS_WT_RENAMED) wstatus = "renamed"; else if (s->status & GIT_STATUS_WT_TYPECHANGE) wstatus = "typechange"; else if (s->status == (GIT_STATUS_INDEX_DELETED | GIT_STATUS_WT_NEW)) wstatus = "unmerged"; else if (s->status & GIT_STATUS_CONFLICTED) wstatus = "conflicted"; if (!wstatus) continue; SET_STRING_ELT(sub_list_names, j, Rf_mkChar(wstatus)); old_path = s->index_to_workdir->old_file.path; new_path = s->index_to_workdir->new_file.path; if (old_path && new_path && strcmp(old_path, new_path)) { SEXP item; SET_VECTOR_ELT(sub_list, j, item = Rf_allocVector(STRSXP, 2)); SET_STRING_ELT(item, 0, Rf_mkChar(old_path)); SET_STRING_ELT(item, 1, Rf_mkChar(new_path)); } else { SEXP item; SET_VECTOR_ELT(sub_list, j, item = Rf_allocVector(STRSXP, 1)); SET_STRING_ELT(item, 0, Rf_mkChar(old_path ? old_path : new_path)); } j++; } } /** * Add untracked files * * @param list The list to hold the result * @param list_index The index in list where to add the new sub list * with untracked files. * @param status_list Representation of a status collection * @return void */ static void git2r_status_list_untracked( SEXP list, size_t list_index, git_status_list *status_list) { size_t i = 0, j = 0, n; SEXP sub_list, sub_list_names; /* Create list with the correct number of entries */ n = git2r_status_count_untracked(status_list); SET_VECTOR_ELT(list, list_index, sub_list = Rf_allocVector(VECSXP, n)); Rf_setAttrib(sub_list, R_NamesSymbol, sub_list_names = Rf_allocVector(STRSXP, n)); /* i index the entrycount. j index the added change in list */ n = git_status_list_entrycount(status_list); for (; i < n; i++) { const git_status_entry *s = git_status_byindex(status_list, i); if (s->status == GIT_STATUS_WT_NEW) { SET_VECTOR_ELT( sub_list, j, Rf_mkString(s->index_to_workdir->old_file.path)); SET_STRING_ELT(sub_list_names, j, Rf_mkChar("untracked")); j++; } } } /** * Get state of the repository working directory and the staging area. * * @param repo S3 class git_repository * @param staged Include staged files. * @param unstaged Include unstaged files. * @param untracked Include untracked files and directories. * @param all_untracked Shows individual files in untracked * directories if 'untracked' is 'TRUE'. * @param ignored Include ignored files. * @return VECXSP with status */ SEXP attribute_hidden git2r_status_list( SEXP repo, SEXP staged, SEXP unstaged, SEXP untracked, SEXP all_untracked, SEXP ignored) { int error, nprotect = 0; size_t i=0, count; SEXP list = R_NilValue; SEXP list_names = R_NilValue; git_repository *repository; git_status_list *status_list = NULL; git_status_options opts = GIT_STATUS_OPTIONS_INIT; if (git2r_arg_check_logical(staged)) git2r_error(__func__, NULL, "'staged'", git2r_err_logical_arg); if (git2r_arg_check_logical(unstaged)) git2r_error(__func__, NULL, "'unstaged'", git2r_err_logical_arg); if (git2r_arg_check_logical(untracked)) git2r_error(__func__, NULL, "'untracked'", git2r_err_logical_arg); if (git2r_arg_check_logical(all_untracked)) git2r_error(__func__, NULL, "'all_untracked'", git2r_err_logical_arg); if (git2r_arg_check_logical(ignored)) git2r_error(__func__, NULL, "'ignored'", git2r_err_logical_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); opts.show = GIT_STATUS_SHOW_INDEX_AND_WORKDIR; opts.flags = GIT_STATUS_OPT_RENAMES_HEAD_TO_INDEX | GIT_STATUS_OPT_SORT_CASE_SENSITIVELY; if (LOGICAL(untracked)[0]) { opts.flags |= GIT_STATUS_OPT_INCLUDE_UNTRACKED; if (LOGICAL(all_untracked)[0]) opts.flags |= GIT_STATUS_OPT_RECURSE_UNTRACKED_DIRS; } if (LOGICAL(ignored)[0]) opts.flags |= GIT_STATUS_OPT_INCLUDE_IGNORED; error = git_status_list_new(&status_list, repository, &opts); if (error) goto cleanup; count = LOGICAL(staged)[0] + LOGICAL(unstaged)[0] + LOGICAL(untracked)[0] + LOGICAL(ignored)[0]; PROTECT(list = Rf_allocVector(VECSXP, count)); nprotect++; Rf_setAttrib(list, R_NamesSymbol, list_names = Rf_allocVector(STRSXP, count)); if (LOGICAL(staged)[0]) { SET_STRING_ELT(list_names, i, Rf_mkChar("staged")); git2r_status_list_staged(list, i, status_list); i++; } if (LOGICAL(unstaged)[0]) { SET_STRING_ELT(list_names, i, Rf_mkChar("unstaged")); git2r_status_list_unstaged(list, i, status_list); i++; } if (LOGICAL(untracked)[0]) { SET_STRING_ELT(list_names, i, Rf_mkChar("untracked")); git2r_status_list_untracked(list, i, status_list); i++; } if (LOGICAL(ignored)[0]) { SET_STRING_ELT(list_names, i, Rf_mkChar("ignored")); git2r_status_list_ignored(list, i, status_list); } cleanup: git_status_list_free(status_list); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return list; } git2r/src/git2r_revwalk.h0000644000176200001440000000223413565053016015030 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2019 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_revwalk_h #define INCLUDE_git2r_revwalk_h #include #include SEXP git2r_revwalk_contributions(SEXP repo, SEXP topological, SEXP time, SEXP reverse); SEXP git2r_revwalk_list(SEXP repo, SEXP sha, SEXP topological, SEXP time, SEXP reverse, SEXP max_n); SEXP git2r_revwalk_list2(SEXP repo, SEXP sha, SEXP topological, SEXP time, SEXP reverse, SEXP max_n, SEXP path); #endif git2r/src/git2r_reflog.h0000644000176200001440000000163113137360640014632 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_reflog_h #define INCLUDE_git2r_reflog_h #include #include SEXP git2r_reflog_list(SEXP repo, SEXP ref); #endif git2r/src/git2r_note.c0000644000176200001440000002644014700264500014314 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_error.h" #include "git2r_note.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_signature.h" /** * Data structure to hold information when iterating over note * objects. */ typedef struct { size_t n; SEXP list; SEXP repo; git_repository *repository; const char *notes_ref; } git2r_note_foreach_cb_data; /** * Init slots in S3 class git_note * * @param blob_id Oid of the blob containing the message * @param annotated_object_id Oid of the git object being annotated * @param repository * @param repo S3 class git_repository that contains the stash * @param dest S3 class git_note to initialize * @return int 0 on success, or an error code. */ static int git2r_note_init( const git_oid *blob_id, const git_oid *annotated_object_id, git_repository *repository, const char *notes_ref, SEXP repo, SEXP dest) { int error; git_note *note = NULL; char sha[GIT_OID_HEXSZ + 1]; error = git_note_read(¬e, repository, notes_ref, annotated_object_id); if (error) return error; git_oid_fmt(sha, blob_id); sha[GIT_OID_HEXSZ] = '\0'; SET_VECTOR_ELT( dest, git2r_S3_item__git_note__sha, Rf_mkString(sha)); git_oid_fmt(sha, annotated_object_id); sha[GIT_OID_HEXSZ] = '\0'; SET_VECTOR_ELT(dest, git2r_S3_item__git_note__annotated, Rf_mkString(sha)); SET_VECTOR_ELT( dest, git2r_S3_item__git_note__message, Rf_mkString(git_note_message(note))); SET_VECTOR_ELT( dest, git2r_S3_item__git_note__refname, Rf_mkString(notes_ref)); SET_VECTOR_ELT( dest, git2r_S3_item__git_note__repo, Rf_duplicate(repo)); git_note_free(note); return 0; } /** * Add a note for an object * * @param repo S3 class git_repository * @param sha The sha string of object * @param commit S3 class git_commit * @param message Content of the note to add * @param ref Canonical name of the reference to use * @param author Signature of the notes note author * @param committer Signature of the notes note committer * @param force Overwrite existing note * @return S3 class git_note */ SEXP attribute_hidden git2r_note_create( SEXP repo, SEXP sha, SEXP message, SEXP ref, SEXP author, SEXP committer, SEXP force) { int error, nprotect = 0; SEXP result = R_NilValue; int overwrite = 0; git_oid note_oid; git_oid object_oid; git_signature *sig_author = NULL; git_signature *sig_committer = NULL; git_repository *repository = NULL; if (git2r_arg_check_sha(sha)) git2r_error(__func__, NULL, "'sha'", git2r_err_sha_arg); if (git2r_arg_check_string(message)) git2r_error(__func__, NULL, "'message'", git2r_err_string_arg); if (git2r_arg_check_string(ref)) git2r_error(__func__, NULL, "'ref'", git2r_err_string_arg); if (git2r_arg_check_signature(author)) git2r_error(__func__, NULL, "'author'", git2r_err_signature_arg); if (git2r_arg_check_signature(committer)) git2r_error(__func__, NULL, "'committer'", git2r_err_signature_arg); if (git2r_arg_check_logical(force)) git2r_error(__func__, NULL, "'force'", git2r_err_logical_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git2r_signature_from_arg(&sig_author, author); if (error) goto cleanup; error = git2r_signature_from_arg(&sig_committer, committer); if (error) goto cleanup; error = git_oid_fromstr(&object_oid, CHAR(STRING_ELT(sha, 0))); if (error) goto cleanup; if (LOGICAL(force)[0]) overwrite = 1; error = git_note_create( ¬e_oid, repository, CHAR(STRING_ELT(ref, 0)), sig_author, sig_committer, &object_oid, CHAR(STRING_ELT(message, 0)), overwrite); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_note)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_note)); error = git2r_note_init(¬e_oid, &object_oid, repository, CHAR(STRING_ELT(ref, 0)), repo, result); cleanup: git_signature_free(sig_author); git_signature_free(sig_committer); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Default notes reference * * Get the default notes reference for a repository * @param repo S3 class git_repository * @return Character vector of length one with name of default * reference */ SEXP attribute_hidden git2r_note_default_ref( SEXP repo) { int error, nprotect = 0; SEXP result = R_NilValue; git_buf buf = GIT_BUF_INIT_CONST(NULL, 0); git_repository *repository = NULL; repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_note_default_ref(&buf, repository); if (error) goto cleanup; PROTECT(result = Rf_allocVector(STRSXP, 1)); nprotect++; SET_STRING_ELT(result, 0, Rf_mkChar(buf.ptr)); cleanup: git_buf_dispose(&buf); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Callback when iterating over notes * * @param blob_id Oid of the blob containing the message * @param annotated_object_id Oid of the git object being annotated * @param payload Payload data passed to `git_note_foreach` * @return int 0 or error code */ static int git2r_note_foreach_cb( const git_oid *blob_id, const git_oid *annotated_object_id, void *payload) { int error = 0, nprotect = 0; SEXP note; git2r_note_foreach_cb_data *cb_data = (git2r_note_foreach_cb_data*)payload; /* Check if we have a list to populate */ if (!Rf_isNull(cb_data->list)) { PROTECT(note = Rf_mkNamed(VECSXP, git2r_S3_items__git_note)); nprotect++; Rf_setAttrib( note, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_note)); error = git2r_note_init( blob_id, annotated_object_id, cb_data->repository, cb_data->notes_ref, cb_data->repo, note); if (error) goto cleanup; SET_VECTOR_ELT(cb_data->list, cb_data->n, note); } cb_data->n += 1; cleanup: if (nprotect) UNPROTECT(nprotect); return error; } /** * List all the notes within a specified namespace. * * @param repo S3 class git_repository * @param ref Optional reference to read from. * @return VECXSP with S3 objects of class git_note */ SEXP attribute_hidden git2r_notes( SEXP repo, SEXP ref) { int error, nprotect = 0; SEXP result = R_NilValue; git_buf buf = GIT_BUF_INIT_CONST(NULL, 0); const char *notes_ref; git2r_note_foreach_cb_data cb_data = {0, R_NilValue, R_NilValue, NULL, NULL}; git_repository *repository = NULL; if (!Rf_isNull(ref)) { if (git2r_arg_check_string(ref)) git2r_error(__func__, NULL, "'ref'", git2r_err_string_arg); } repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); if (!Rf_isNull(ref)) { notes_ref = CHAR(STRING_ELT(ref, 0)); } else { error = git_note_default_ref(&buf, repository); if (error) goto cleanup; notes_ref = buf.ptr; } /* Count number of notes before creating the list */ error = git_note_foreach( repository, notes_ref, &git2r_note_foreach_cb, &cb_data); if (error) { if (GIT_ENOTFOUND == error) { error = GIT_OK; PROTECT(result = Rf_allocVector(VECSXP, 0)); nprotect++; } goto cleanup; } PROTECT(result = Rf_allocVector(VECSXP, cb_data.n)); nprotect++; cb_data.n = 0; cb_data.list = result; cb_data.repo = repo; cb_data.repository = repository; cb_data.notes_ref = notes_ref; error = git_note_foreach(repository, notes_ref, &git2r_note_foreach_cb, &cb_data); cleanup: git_buf_dispose(&buf); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Remove the note for an object * * @param note S3 class git_note * @param author Signature of the notes commit author * @param committer Signature of the notes commit committer * @return R_NilValue */ SEXP attribute_hidden git2r_note_remove( SEXP note, SEXP author, SEXP committer) { int error; SEXP repo; SEXP annotated; git_oid note_oid; git_signature *sig_author = NULL; git_signature *sig_committer = NULL; git_repository *repository = NULL; if (git2r_arg_check_note(note)) git2r_error(__func__, NULL, "'note'", git2r_err_note_arg); if (git2r_arg_check_signature(author)) git2r_error(__func__, NULL, "'author'", git2r_err_signature_arg); if (git2r_arg_check_signature(committer)) git2r_error(__func__, NULL, "'committer'", git2r_err_signature_arg); repo = git2r_get_list_element(note, "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git2r_signature_from_arg(&sig_author, author); if (error) goto cleanup; error = git2r_signature_from_arg(&sig_committer, committer); if (error) goto cleanup; annotated = git2r_get_list_element(note, "annotated"); error = git_oid_fromstr(¬e_oid, CHAR(STRING_ELT(annotated, 0))); if (error) goto cleanup; error = git_note_remove( repository, CHAR(STRING_ELT(git2r_get_list_element(note, "refname"), 0)), sig_author, sig_committer, ¬e_oid); cleanup: git_signature_free(sig_author); git_signature_free(sig_committer); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } git2r/src/git2r_branch.c0000644000176200001440000005531114700530422014602 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_branch.h" #include "git2r_commit.h" #include "git2r_error.h" #include "git2r_reference.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_signature.h" /** * Count number of branches. * * @param repo S3 class git_repository * @param flags Filtering flags for the branch listing. Valid values * are 1 (LOCAL), 2 (REMOTE) and 3 (ALL) * @param n The number of branches * @return 0 on success, or an error code. */ static int git2r_branch_count( git_repository *repo, int flags, size_t *n) { int error; git_branch_iterator *iter; git_branch_t type; git_reference *ref; *n = 0; error = git_branch_iterator_new(&iter, repo, flags); if (error) return error; for (;;) { error = git_branch_next(&ref, &type, iter); if (error) break; git_reference_free(ref); (*n)++; } git_branch_iterator_free(iter); if (GIT_ITEROVER != error) return error; return 0; } /** * Init slots in S3 class git_branch * * @param source a reference * @param repository the repository * @param type the branch type; local or remote * @param repo S3 class git_repository that contains the blob * @param dest S3 class git_branch to initialize * @return int; < 0 if error, else 0 */ int attribute_hidden git2r_branch_init( const git_reference *source, git_branch_t type, SEXP repo, SEXP dest) { int error; const char *name; error = git_branch_name(&name, source); if (error) goto cleanup; SET_VECTOR_ELT(dest, git2r_S3_item__git_branch__name, Rf_mkString(name)); SET_VECTOR_ELT(dest, git2r_S3_item__git_branch__type, Rf_ScalarInteger(type)); SET_VECTOR_ELT(dest, git2r_S3_item__git_branch__repo, Rf_duplicate(repo)); cleanup: return error; } /** * Create a new branch * * @param branch_name Name for the branch * @param commit Commit to which branch should point. * @param force Overwrite existing branch * @return S3 class git_branch */ SEXP attribute_hidden git2r_branch_create( SEXP branch_name, SEXP commit, SEXP force) { SEXP repo, result = R_NilValue; int error, nprotect = 0, overwrite = 0; git_commit *target = NULL; git_reference *reference = NULL; git_repository *repository = NULL; if (git2r_arg_check_string(branch_name)) git2r_error(__func__, NULL, "'branch_name'", git2r_err_string_arg); if (git2r_arg_check_commit(commit)) git2r_error(__func__, NULL, "'commit'", git2r_err_commit_arg); if (git2r_arg_check_logical(force)) git2r_error(__func__, NULL, "'force'", git2r_err_logical_arg); repo = git2r_get_list_element(commit, "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git2r_commit_lookup(&target, repository, commit); if (error) goto cleanup; if (LOGICAL(force)[0]) overwrite = 1; error = git_branch_create( &reference, repository, CHAR(STRING_ELT(branch_name, 0)), target, overwrite); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_branch)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_branch)); error = git2r_branch_init(reference, GIT_BRANCH_LOCAL, repo, result); cleanup: git_reference_free(reference); git_commit_free(target); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Delete branch * * @param branch S3 class git_branch * @return R_NilValue */ SEXP attribute_hidden git2r_branch_delete( SEXP branch) { int error; const char *name; git_branch_t type; git_reference *reference = NULL; git_repository *repository = NULL; if (git2r_arg_check_branch(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg); repository = git2r_repository_open(git2r_get_list_element(branch, "repo")); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); name = CHAR(STRING_ELT(git2r_get_list_element(branch, "name"), 0)); type = INTEGER(git2r_get_list_element(branch, "type"))[0]; error = git_branch_lookup(&reference, repository, name, type); if (error) goto cleanup; error = git_branch_delete(reference); cleanup: git_reference_free(reference); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Determine if the current local branch is pointed at by HEAD * * @param branch S3 class git_branch * @return TRUE if head, FALSE if not */ SEXP attribute_hidden git2r_branch_is_head( SEXP branch) { SEXP result = R_NilValue; int error, nprotect = 0; const char *name; git_reference *reference = NULL; git_repository *repository = NULL; if (git2r_arg_check_branch(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg); repository = git2r_repository_open(git2r_get_list_element(branch, "repo")); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); name = CHAR(STRING_ELT(git2r_get_list_element(branch, "name"), 0)); error = git_branch_lookup( &reference, repository, name, INTEGER(git2r_get_list_element(branch, "type"))[0]); if (error) goto cleanup; error = git_branch_is_head(reference); if (0 == error || 1 == error) { PROTECT(result = Rf_allocVector(LGLSXP, 1)); nprotect++; LOGICAL(result)[0] = error; error = 0; } cleanup: git_reference_free(reference); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * List branches in a repository * * @param repo S3 class git_repository * @param flags Filtering flags for the branch listing. Valid values * are 1 (LOCAL), 2 (REMOTE) and 3 (ALL) * @return VECXSP with S3 objects of class git_branch */ SEXP attribute_hidden git2r_branch_list( SEXP repo, SEXP flags) { SEXP names, result = R_NilValue; int error, nprotect = 0; git_branch_iterator *iter = NULL; size_t i, n = 0; git_repository *repository = NULL; git_reference *reference = NULL; git_branch_t type; if (git2r_arg_check_integer(flags)) git2r_error(__func__, NULL, "'flags'", git2r_err_integer_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); /* Count number of branches before creating the list */ error = git2r_branch_count(repository, INTEGER(flags)[0], &n); if (error) goto cleanup; PROTECT(result = Rf_allocVector(VECSXP, n)); nprotect++; Rf_setAttrib(result, R_NamesSymbol, names = Rf_allocVector(STRSXP, n)); error = git_branch_iterator_new(&iter, repository, INTEGER(flags)[0]); if (error) goto cleanup; for (i = 0; i < n; i++) { SEXP branch; error = git_branch_next(&reference, &type, iter); if (error) { if (GIT_ITEROVER == error) error = GIT_OK; goto cleanup; } SET_VECTOR_ELT(result, i, branch = Rf_mkNamed(VECSXP, git2r_S3_items__git_branch)); Rf_setAttrib(branch, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_branch)); error = git2r_branch_init(reference, type, repo, branch); if (error) goto cleanup; SET_STRING_ELT( names, i, STRING_ELT(git2r_get_list_element(branch, "name"), 0)); if (reference) git_reference_free(reference); reference = NULL; } cleanup: git_branch_iterator_free(iter); git_reference_free(reference); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Get the full name of a branch * * @param branch S3 class git_branch * @return character string with full name of branch. */ SEXP attribute_hidden git2r_branch_canonical_name( SEXP branch) { int error, nprotect = 0; SEXP result = R_NilValue; const char *name; git_branch_t type; git_reference *reference = NULL; git_repository *repository = NULL; if (git2r_arg_check_branch(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg); repository = git2r_repository_open(git2r_get_list_element(branch, "repo")); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); name = CHAR(STRING_ELT(git2r_get_list_element(branch, "name"), 0)); type = INTEGER(git2r_get_list_element(branch, "type"))[0]; error = git_branch_lookup(&reference, repository, name, type); if (error) goto cleanup; PROTECT(result = Rf_allocVector(STRSXP, 1)); nprotect++; SET_STRING_ELT(result, 0, Rf_mkChar(git_reference_name(reference))); cleanup: git_reference_free(reference); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Get the configured canonical name of the upstream branch, given a * local branch, i.e "branch.branch_name.merge" property of the config * file. * * @param branch S3 class git_branch. * @return Character vector of length one with upstream canonical name. */ SEXP attribute_hidden git2r_branch_upstream_canonical_name( SEXP branch) { int error, nprotect = 0; SEXP result = R_NilValue; SEXP repo; const char *name; git_branch_t type; const char *branch_name; size_t branch_name_len; char *buf = NULL; size_t buf_len; git_config *cfg = NULL; git_repository *repository = NULL; if (git2r_arg_check_branch(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg); type = INTEGER(git2r_get_list_element(branch, "type"))[0]; if (GIT_BRANCH_LOCAL != type) git2r_error(__func__, NULL, git2r_err_branch_not_local, NULL); repo = git2r_get_list_element(branch, "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_repository_config_snapshot(&cfg, repository); if (error) goto cleanup; branch_name = CHAR(STRING_ELT(git2r_get_list_element(branch, "name"), 0)); branch_name_len = strlen(branch_name); while (branch_name[0] == '.') { branch_name++; branch_name_len--; } while (branch_name_len >= 1 && branch_name[branch_name_len - 1] == '.') { branch_name_len--; } buf_len = branch_name_len + sizeof("branch." ".merge"); buf = malloc(buf_len); if (!buf) { giterr_set_oom(); error = GIT_ERROR_NOMEMORY; goto cleanup; } error = snprintf(buf, buf_len, "branch.%.*s.merge", (int)branch_name_len, branch_name); if (error < 0 || (size_t)error >= buf_len) { giterr_set_str(GIT_ERROR_OS, "Failed to snprintf branch config."); error = GIT_ERROR_OS; goto cleanup; } error = git_config_get_string(&name, cfg, buf); if (error) goto cleanup; PROTECT(result = Rf_allocVector(STRSXP, 1)); nprotect++; SET_STRING_ELT(result, 0, Rf_mkChar(name)); cleanup: if (buf) free(buf); git_config_free(cfg); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Get remote name of branch * * @param branch S3 class git_branch * @return character string with remote name. */ SEXP attribute_hidden git2r_branch_remote_name( SEXP branch) { int error, nprotect = 0; SEXP result = R_NilValue; const char *name; git_buf buf = {0}; git_branch_t type; git_reference *reference = NULL; git_repository *repository = NULL; if (git2r_arg_check_branch(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg); type = INTEGER(git2r_get_list_element(branch, "type"))[0]; if (GIT_BRANCH_REMOTE != type) git2r_error(__func__, NULL, git2r_err_branch_not_remote, NULL); repository = git2r_repository_open(git2r_get_list_element(branch, "repo")); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); name = CHAR(STRING_ELT(git2r_get_list_element(branch, "name"), 0)); error = git_branch_lookup(&reference, repository, name, type); if (error) goto cleanup; error = git_branch_remote_name( &buf, repository, git_reference_name(reference)); if (error) goto cleanup; PROTECT(result = Rf_allocVector(STRSXP, 1)); nprotect++; SET_STRING_ELT(result, 0, Rf_mkChar(buf.ptr)); git_buf_dispose(&buf); cleanup: git_reference_free(reference); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Get remote url of branch * * @param branch S3 class git_branch * @return character string with remote url. */ SEXP attribute_hidden git2r_branch_remote_url( SEXP branch) { int error, nprotect = 0; SEXP result = R_NilValue; const char *name; git_buf buf = {0}; git_branch_t type; git_reference *reference = NULL; git_remote *remote = NULL; git_repository *repository = NULL; if (git2r_arg_check_branch(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg); type = INTEGER(git2r_get_list_element(branch, "type"))[0]; if (GIT_BRANCH_REMOTE != type) git2r_error(__func__, NULL, git2r_err_branch_not_remote, NULL); repository = git2r_repository_open(git2r_get_list_element(branch, "repo")); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); name = CHAR(STRING_ELT(git2r_get_list_element(branch, "name"), 0)); error = git_branch_lookup(&reference, repository, name, type); if (error) goto cleanup; error = git_branch_remote_name( &buf, repository, git_reference_name(reference)); if (error) goto cleanup; error = git_remote_lookup(&remote, repository, buf.ptr); if (error) { error = git_remote_create_anonymous(&remote, repository, buf.ptr); if (error) { git_buf_dispose(&buf); goto cleanup; } } git_buf_dispose(&buf); PROTECT(result = Rf_allocVector(STRSXP, 1)); nprotect++; SET_STRING_ELT(result, 0, Rf_mkChar(git_remote_url(remote))); cleanup: git_remote_free(remote); git_reference_free(reference); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Rename a branch * * @param branch Branch to rename * @param new_branch_name The new name for the branch * @param force Overwrite existing branch * @return The renamed S3 class git_branch */ SEXP attribute_hidden git2r_branch_rename( SEXP branch, SEXP new_branch_name, SEXP force) { SEXP repo, result = R_NilValue; int error, nprotect = 0, overwrite = 0; const char *name = NULL; git_branch_t type; git_reference *reference = NULL, *new_reference = NULL; git_repository *repository = NULL; if (git2r_arg_check_branch(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg); if (git2r_arg_check_string(new_branch_name)) git2r_error(__func__, NULL, "'new_branch_name'", git2r_err_string_arg); if (git2r_arg_check_logical(force)) git2r_error(__func__, NULL, "'force'", git2r_err_logical_arg); repo = git2r_get_list_element(branch, "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); type = INTEGER(git2r_get_list_element(branch, "type"))[0]; name = CHAR(STRING_ELT(git2r_get_list_element(branch, "name"), 0)); error = git_branch_lookup(&reference, repository, name, type); if (error) goto cleanup; if (LOGICAL(force)[0]) overwrite = 1; error = git_branch_move( &new_reference, reference, CHAR(STRING_ELT(new_branch_name, 0)), overwrite); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_branch)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_branch)); error = git2r_branch_init(new_reference, type, repo, result); cleanup: git_reference_free(reference); git_reference_free(new_reference); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Get sha pointed to by a branch * * @param branch S3 class git_branch * @return The 40 character sha if the reference is direct, else NA */ SEXP attribute_hidden git2r_branch_target( SEXP branch) { int error, nprotect = 0; SEXP result = R_NilValue; const char *name; char sha[GIT_OID_HEXSZ + 1]; git_branch_t type; git_reference *reference = NULL; git_repository *repository = NULL; if (git2r_arg_check_branch(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg); repository = git2r_repository_open(git2r_get_list_element(branch, "repo")); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); name = CHAR(STRING_ELT(git2r_get_list_element(branch, "name"), 0)); type = INTEGER(git2r_get_list_element(branch, "type"))[0]; error = git_branch_lookup(&reference, repository, name, type); if (error) goto cleanup; PROTECT(result = Rf_allocVector(STRSXP, 1)); nprotect++; if (git_reference_type(reference) == GIT_REFERENCE_DIRECT) { git_oid_fmt(sha, git_reference_target(reference)); sha[GIT_OID_HEXSZ] = '\0'; SET_STRING_ELT(result, 0, Rf_mkChar(sha)); } else { SET_STRING_ELT(result, 0, NA_STRING); } cleanup: git_reference_free(reference); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Get remote tracking branch, given a local branch. * * @param branch S3 class git_branch * @return S3 class git_branch or R_NilValue if no remote tracking branch. */ SEXP attribute_hidden git2r_branch_get_upstream( SEXP branch) { int error, nprotect = 0; SEXP repo, result = R_NilValue; const char *name; git_branch_t type; git_reference *reference = NULL, *upstream = NULL; git_repository *repository = NULL; if (git2r_arg_check_branch(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg); repo = git2r_get_list_element(branch, "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); name = CHAR(STRING_ELT(git2r_get_list_element(branch, "name"), 0)); type = INTEGER(git2r_get_list_element(branch, "type"))[0]; error = git_branch_lookup(&reference, repository, name, type); if (error) goto cleanup; error = git_branch_upstream(&upstream, reference); if (error) { if (GIT_ENOTFOUND == error) error = GIT_OK; goto cleanup; } PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_branch)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_branch)); error = git2r_branch_init(upstream, GIT_BRANCH_REMOTE, repo, result); cleanup: git_reference_free(reference); git_reference_free(upstream); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Set remote tracking branch * * Set the upstream configuration for a given local branch * @param branch The branch to configure * @param upstream_name remote-tracking or local branch to set as * upstream. Pass NULL to unset. * @return R_NilValue */ SEXP attribute_hidden git2r_branch_set_upstream( SEXP branch, SEXP upstream_name) { int error; SEXP repo; const char *name; const char *u_name = NULL; git_branch_t type; git_reference *reference = NULL; git_repository *repository = NULL; if (git2r_arg_check_branch(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg); if (!Rf_isNull(upstream_name)) { if (git2r_arg_check_string(upstream_name)) git2r_error(__func__, NULL, "'upstream_name'", git2r_err_string_arg); u_name = CHAR(STRING_ELT(upstream_name, 0)); } repo = git2r_get_list_element(branch, "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); name = CHAR(STRING_ELT(git2r_get_list_element(branch, "name"), 0)); type = INTEGER(git2r_get_list_element(branch, "type"))[0]; error = git_branch_lookup(&reference, repository, name, type); if (error) goto cleanup; error = git_branch_set_upstream(reference, u_name); cleanup: git_reference_free(reference); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } git2r/src/git2r_S3.c0000644000176200001440000001117413671131056013637 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2020 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_S3.h" const char *git2r_S3_class__git_blame = "git_blame"; const char *git2r_S3_items__git_blame[] = { "path", "hunks", "repo", ""}; const char *git2r_S3_class__git_blame_hunk = "git_blame_hunk"; const char *git2r_S3_items__git_blame_hunk[] = { "lines_in_hunk", "final_commit_id", "final_start_line_number", "final_signature", "orig_commit_id", "orig_start_line_number", "orig_signature", "orig_path", "boundary", "repo", ""}; const char *git2r_S3_class__git_blob = "git_blob"; const char *git2r_S3_items__git_blob[] = { "sha", "repo", ""}; const char *git2r_S3_class__git_branch = "git_branch"; const char *git2r_S3_items__git_branch[] = { "name", "type", "repo", ""}; const char *git2r_S3_class__git_commit = "git_commit"; const char *git2r_S3_items__git_commit[] = { "sha", "author", "committer", "summary", "message", "repo", ""}; const char *git2r_S3_class__git_diff = "git_diff"; const char *git2r_S3_items__git_diff[] = { "old", "new", "files", ""}; const char *git2r_S3_class__git_diff_file = "git_diff_file"; const char *git2r_S3_items__git_diff_file[] = { "old_file", "new_file", "hunks", ""}; const char *git2r_S3_class__git_diff_hunk = "git_diff_hunk"; const char *git2r_S3_items__git_diff_hunk[] = { "old_start", "old_lines", "new_start", "new_lines", "header", "lines", ""}; const char *git2r_S3_class__git_diff_line = "git_diff_line"; const char *git2r_S3_items__git_diff_line[] = { "origin", "old_lineno", "new_lineno", "num_lines", "content", ""}; const char *git2r_S3_class__git_fetch_head = "git_fetch_head"; const char *git2r_S3_items__git_fetch_head[] = { "ref_name", "remote_url", "sha", "is_merge", "repo", ""}; const char *git2r_S3_class__git_merge_result = "git_merge_result"; const char *git2r_S3_items__git_merge_result[] = { "up_to_date", "fast_forward", "conflicts", "sha", ""}; const char *git2r_S3_class__git_note = "git_note"; const char *git2r_S3_items__git_note[] = { "sha", "annotated", "message", "refname", "repo", ""}; const char *git2r_S3_class__git_reference = "git_reference"; const char *git2r_S3_items__git_reference[] = { "name", "type", "sha", "target", "shorthand", "repo", ""}; const char *git2r_S3_class__git_reflog_entry = "git_reflog_entry"; const char *git2r_S3_items__git_reflog_entry[] = { "sha", "message", "index", "committer", "refname", "repo", ""}; const char *git2r_S3_class__git_repository = "git_repository"; const char *git2r_S3_items__git_repository[] = { "path", ""}; const char *git2r_S3_class__git_signature = "git_signature"; const char *git2r_S3_items__git_signature[] = { "name", "email", "when", ""}; const char *git2r_S3_class__git_tag = "git_tag"; const char *git2r_S3_items__git_tag[] = { "sha", "message", "name", "tagger", "target", "repo", ""}; const char *git2r_S3_class__git_time = "git_time"; const char *git2r_S3_items__git_time[] = { "time", "offset", ""}; const char *git2r_S3_class__git_transfer_progress = "git_transfer_progress"; const char *git2r_S3_items__git_transfer_progress[] = { "total_objects", "indexed_objects", "received_objects", "local_objects", "total_deltas", "indexed_deltas", "received_bytes", ""}; const char *git2r_S3_class__git_tree = "git_tree"; const char *git2r_S3_items__git_tree[] = { "sha", "filemode", "type", "id", "name", "repo", ""}; /** * Get the list element named str, or return NULL. * * From the manual 'Writing R Extensions' * (https://cran.r-project.org/doc/manuals/r-release/R-exts.html) */ SEXP attribute_hidden git2r_get_list_element( SEXP list, const char *str) { int i = 0; SEXP elmt = R_NilValue, names = Rf_getAttrib(list, R_NamesSymbol); for (; i < Rf_length(list); i++) { if(strcmp(CHAR(STRING_ELT(names, i)), str) == 0) { elmt = VECTOR_ELT(list, i); break; } } return elmt; } git2r/src/git2r_cred.c0000644000176200001440000003326714700261602014271 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #ifdef WIN32 #include #include # ifndef WC_ERR_INVALID_CHARS # define WC_ERR_INVALID_CHARS 0x80 # endif #endif #include #include #include #include "git2r_arg.h" #include "git2r_cred.h" #include "git2r_S3.h" #include "git2r_transfer.h" #define GIT2R_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) /** * Read an environtmental variable. * * @param out Pointer where to store the environmental variable. * @param obj The S3 object with name of the environmental * variable to read. * @param slot The slot in the S3 object with the name of the * environmental variable. * @return 0 on success, else -1. */ static int git2r_getenv( char **out, SEXP obj, const char *slot) { const char *buf; /* Read value of the environment variable */ buf = getenv(CHAR(STRING_ELT(git2r_get_list_element(obj, slot), 0))); if (!buf || !strlen(buf)) return -1; *out = malloc(strlen(buf)+1); if (!*out) return -1; strcpy(*out, buf); return 0; } /** * Create credential object from S3 class 'cred_ssh_key'. * * @param cred The newly created credential object. * @param user_from_url The username that was embedded in a "user@host" * @param allowed_types A bitmask stating which cred types are OK to return. * @param credentials The S3 class object with credentials. * @return 0 on success, else -1. */ static int git2r_cred_ssh_key( git_credential **cred, const char *username_from_url, unsigned int allowed_types, SEXP credentials) { if (GIT_CREDENTIAL_SSH_KEY & allowed_types) { SEXP elem; const char *publickey; const char *privatekey = NULL; const char *passphrase = NULL; publickey = CHAR(STRING_ELT(git2r_get_list_element(credentials, "publickey"), 0)); privatekey = CHAR(STRING_ELT(git2r_get_list_element(credentials, "privatekey"), 0)); elem = git2r_get_list_element(credentials, "passphrase"); if (Rf_length(elem) && (NA_STRING != STRING_ELT(elem, 0))) passphrase = CHAR(STRING_ELT(elem, 0)); if (git_credential_ssh_key_new( cred, username_from_url, publickey, privatekey, passphrase)) return -1; return 0; } return -1; } /** * Create credential object from S3 class 'cred_env'. * * @param cred The newly created credential object. * @param allowed_types A bitmask stating which cred types are OK to return. * @param credentials The S3 class object with credentials. * @return 0 on success, else -1. */ static int git2r_cred_env( git_credential **cred, unsigned int allowed_types, SEXP credentials) { if (GIT_CREDENTIAL_USERPASS_PLAINTEXT & allowed_types) { int error; char *username = NULL; char *password = NULL; /* Read value of the username environment variable */ error = git2r_getenv(&username, credentials, "username"); if (error) goto cleanup; /* Read value of the password environment variable */ error = git2r_getenv(&password, credentials, "password"); if (error) goto cleanup; error = git_credential_userpass_plaintext_new( cred, username, password); cleanup: free(username); free(password); if (error) return -1; return 0; } return -1; } /** * Create credential object from S3 class 'cred_token'. * * @param cred The newly created credential object. * @param allowed_types A bitmask stating which cred types are OK to return. * @param credentials The S3 class object with credentials. * @return 0 on success, else -1. */ static int git2r_cred_token( git_credential **cred, unsigned int allowed_types, SEXP credentials) { if (GIT_CREDENTIAL_USERPASS_PLAINTEXT & allowed_types) { int error; char *token = NULL; /* Read value of the personal access token from the * environment variable */ error = git2r_getenv(&token, credentials, "token"); if (error) goto cleanup; error = git_credential_userpass_plaintext_new(cred, " ", token); cleanup: free(token); if (error) return -1; return 0; } return -1; } /** * Create credential object from S3 class 'cred_user_pass'. * * @param cred The newly created credential object. * @param allowed_types A bitmask stating which cred types are OK to return. * @param credentials The S3 class object with credentials. * @return 0 on success, else -1. */ static int git2r_cred_user_pass( git_credential **cred, unsigned int allowed_types, SEXP credentials) { if (GIT_CREDENTIAL_USERPASS_PLAINTEXT & allowed_types) { const char *username; const char *password; username = CHAR(STRING_ELT(git2r_get_list_element(credentials, "username"), 0)); password = CHAR(STRING_ELT(git2r_get_list_element(credentials, "password"), 0)); if (git_credential_userpass_plaintext_new(cred, username, password)) return -1; return 0; } return -1; } /* static int git2r_join_str(char** out, const char *str_a, const char *str_b) */ /* { */ /* int len_a, len_b; */ /* if (!str_a || !str_b) */ /* return -1; */ /* len_a = strlen(str_a); */ /* len_b = strlen(str_b); */ /* *out = malloc(len_a + len_b + 1); */ /* if (!*out) */ /* return -1; */ /* if (len_a) */ /* memcpy(*out, str_a, len_a); */ /* if (len_b) */ /* memcpy(*out + len_a, str_b, len_b); */ /* (*out)[len_a + len_b] = '\0'; */ /* return 0; */ /* } */ /* static int git2r_file_exists(const char *path) */ /* { */ /* #ifdef WIN32 */ /* struct _stati64 sb; */ /* return _stati64(path, &sb) == 0; */ /* #else */ /* struct stat sb; */ /* return stat(path, &sb) == 0; */ /* #endif */ /* } */ /* #ifdef WIN32 */ /* static int git2r_expand_key(char** out, const wchar_t *key, const char *ext) */ /* { */ /* wchar_t wbuf[MAX_PATH]; */ /* char *buf_utf8 = NULL; */ /* DWORD len_wbuf; */ /* int len_utf8; */ /* *out = NULL; */ /* if (!key || !ext) */ /* goto on_error; */ /* /\* Expands environment-variable strings and replaces them with the */ /* * values defined for the current user. *\/ */ /* len_wbuf = ExpandEnvironmentStringsW(key, wbuf, GIT2R_ARRAY_SIZE(wbuf)); */ /* if (!len_wbuf || len_wbuf > GIT2R_ARRAY_SIZE(wbuf)) */ /* goto on_error; */ /* /\* Map wide character string to a new utf8 character string. *\/ */ /* len_utf8 = WideCharToMultiByte( */ /* CP_UTF8, WC_ERR_INVALID_CHARS, wbuf,-1, NULL, 0, NULL, NULL); */ /* if (!len_utf8) */ /* goto on_error; */ /* buf_utf8 = malloc(len_utf8); */ /* if (!buf_utf8) */ /* goto on_error; */ /* len_utf8 = WideCharToMultiByte( */ /* CP_UTF8, WC_ERR_INVALID_CHARS, wbuf, -1, buf_utf8, len_utf8, NULL, NULL); */ /* if (!len_utf8) */ /* goto on_error; */ /* if (git2r_join_str(out, buf_utf8, ext)) */ /* goto on_error; */ /* free(buf_utf8); */ /* if (git2r_file_exists(*out)) */ /* return 0; */ /* on_error: */ /* free(buf_utf8); */ /* free(*out); */ /* *out = NULL; */ /* return -1; */ /* } */ /* #else */ /* static int git2r_expand_key(char** out, const char *key, const char *ext) */ /* { */ /* const char *buf = R_ExpandFileName(key); */ /* *out = NULL; */ /* if (!key || !ext) */ /* return -1; */ /* if (git2r_join_str(out, buf, ext)) */ /* return -1; */ /* if (git2r_file_exists(*out)) */ /* return 0; */ /* free(*out); */ /* *out = NULL; */ /* return -1; */ /* } */ /* #endif */ /* static int git2r_ssh_key_needs_passphrase(const char *key) */ /* { */ /* size_t i; */ /* FILE* file = fopen(key, "r"); */ /* if (file == NULL) */ /* return 0; */ /* /\* Look for "ENCRYPTED" in the first three lines. *\/ */ /* for (i = 0; i < 3; i++) { */ /* char str[128] = {0}; */ /* if (fgets(str, GIT2R_ARRAY_SIZE(str), file) != NULL) { */ /* if (strstr(str, "ENCRYPTED") != NULL) { */ /* fclose(file); */ /* return 1; */ /* } */ /* } else { */ /* fclose(file); */ /* return 0; */ /* } */ /* } */ /* fclose(file); */ /* return 0; */ /* } */ /* static int git2r_cred_default_ssh_key( */ /* git_credential **cred, */ /* const char *username_from_url) */ /* { */ /* #ifdef WIN32 */ /* static const wchar_t *key_patterns[3] = */ /* {L"%HOME%\\.ssh\\id_rsa", */ /* L"%HOMEDRIVE%%HOMEPATH%\\.ssh\\id_rsa", */ /* L"%USERPROFILE%\\.ssh\\id_rsa"}; */ /* #else */ /* static const char *key_patterns[1] = {"~/.ssh/id_rsa"}; */ /* #endif */ /* size_t i; */ /* int error = 1; */ /* /\* Find key. *\/ */ /* for (i = 0; i < GIT2R_ARRAY_SIZE(key_patterns); i++) { */ /* char *private_key = NULL; */ /* char *public_key = NULL; */ /* const char *passphrase = NULL; */ /* SEXP pass, askpass, call; */ /* int nprotect = 0; */ /* /\* Expand key pattern and check if files exists. *\/ */ /* if (git2r_expand_key(&private_key, key_patterns[i], "") || */ /* git2r_expand_key(&public_key, key_patterns[i], ".pub")) */ /* { */ /* free(private_key); */ /* free(public_key); */ /* continue; */ /* } */ /* if (git2r_ssh_key_needs_passphrase(private_key)) { */ /* /\* Use the R package getPass to ask for the passphrase. *\/ */ /* PROTECT(pass = Rf_eval(Rf_lang2(Rf_install("getNamespace"), */ /* Rf_ScalarString(Rf_mkChar("getPass"))), */ /* R_GlobalEnv)); */ /* nprotect++; */ /* PROTECT(call = Rf_lcons( */ /* Rf_findFun(Rf_install("getPass"), pass), */ /* Rf_lcons(Rf_mkString("Enter passphrase: "), */ /* R_NilValue))); */ /* nprotect++; */ /* PROTECT(askpass = Rf_eval(call, pass)); */ /* nprotect++; */ /* if (git2r_arg_check_string(askpass) == 0) */ /* passphrase = CHAR(STRING_ELT(askpass, 0)); */ /* } */ /* error = git_cred_ssh_key_new( */ /* cred, */ /* username_from_url, */ /* public_key, */ /* private_key, */ /* passphrase); */ /* /\* Cleanup. *\/ */ /* free(private_key); */ /* free(public_key); */ /* if (nprotect) */ /* UNPROTECT(nprotect); */ /* break; */ /* } */ /* if (error) */ /* return -1; */ /* return 0; */ /* } */ /** * Callback if the remote host requires authentication in order to * connect to it * * @param cred The newly created credential object. * @param url The resource for which we are demanding a credential. * @param user_from_url The username that was embedded in a "user@host" * remote url, or NULL if not included. * @param allowed_types A bitmask stating which cred types are OK to return. * @param payload The payload provided when specifying this callback. * @return 0 on success, else -1. */ int attribute_hidden git2r_cred_acquire_cb( git_credential **cred, const char *url, const char *username_from_url, unsigned int allowed_types, void *payload) { git2r_transfer_data *td; SEXP credentials; GIT2R_UNUSED(url); if (!payload) return -1; td = (git2r_transfer_data*)payload; credentials = td->credentials; if (Rf_isNull(credentials)) { if (GIT_CREDENTIAL_SSH_KEY & allowed_types) { if (td->use_ssh_agent) { /* Try to get credentials from the ssh-agent. */ td->use_ssh_agent = 0; if (git_credential_ssh_key_from_agent(cred, username_from_url) == 0) return 0; } /* if (td->use_ssh_key) { */ /* /\* Try to get credentials from default ssh key. *\/ */ /* td->use_ssh_key = 0; */ /* if (git2r_cred_default_ssh_key(cred, username_from_url) == 0) */ /* return 0; */ /* } */ } return -1; } if (Rf_inherits(credentials, "cred_ssh_key")) { return git2r_cred_ssh_key( cred, username_from_url, allowed_types, credentials); } else if (Rf_inherits(credentials, "cred_env")) { return git2r_cred_env(cred, allowed_types, credentials); } else if (Rf_inherits(credentials, "cred_token")) { return git2r_cred_token(cred, allowed_types, credentials); } else if (Rf_inherits(credentials, "cred_user_pass")) { return git2r_cred_user_pass(cred, allowed_types, credentials); } return -1; } git2r/src/git2r_arg.h0000644000176200001440000000336713525341463014140 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2019 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_arg_h #define INCLUDE_git2r_arg_h #include #include #include #define GIT2R_UNUSED(x) ((void)(x)) int git2r_arg_check_blob(SEXP arg); int git2r_arg_check_branch(SEXP arg); int git2r_arg_check_commit(SEXP arg); int git2r_arg_check_commit_stash(SEXP arg); int git2r_arg_check_credentials(SEXP arg); int git2r_arg_check_fetch_heads(SEXP arg); int git2r_arg_check_filename(SEXP arg); int git2r_arg_check_sha(SEXP arg); int git2r_arg_check_integer(SEXP arg); int git2r_arg_check_integer_gte_zero(SEXP arg); int git2r_arg_check_list(SEXP arg); int git2r_arg_check_logical(SEXP arg); int git2r_arg_check_note(SEXP arg); int git2r_arg_check_repository(SEXP arg); int git2r_arg_check_same_repo(SEXP arg1, SEXP arg2); int git2r_arg_check_signature(SEXP arg); int git2r_arg_check_string(SEXP arg); int git2r_arg_check_string_vec(SEXP arg); int git2r_arg_check_tag(SEXP arg); int git2r_arg_check_tree(SEXP arg); int git2r_copy_string_vec(git_strarray *dst, SEXP src); #endif git2r/src/git2r_diff.c0000644000176200001440000010547214700262065014266 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "git2r_arg.h" #include "git2r_diff.h" #include "git2r_error.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_tree.h" #include #include #include #include #include static int git2r_diff_count( git_diff *diff, size_t *num_files, size_t *max_hunks, size_t *max_lines); static int git2r_diff_format_to_r( git_diff *diff, SEXP dest); SEXP git2r_diff_index_to_wd( SEXP repo, SEXP filename, git_diff_options *opts); SEXP git2r_diff_head_to_index( SEXP repo, SEXP filename, git_diff_options *opts); SEXP git2r_diff_tree_to_wd( SEXP tree, SEXP filename, git_diff_options *opts); SEXP git2r_diff_tree_to_index( SEXP tree, SEXP filename, git_diff_options *opts); SEXP git2r_diff_tree_to_tree( SEXP tree1, SEXP tree2, SEXP filename, git_diff_options *opts); /** * Diff * * Setting index to TRUE is essentially like supplying the --cached * option to command line git. * * - If tree1 is NULL and index is FALSE, then we compare the working * directory to the index. (tree2 must be NULL in this case.) * - If tree1 is NULL and index is TRUE, then we compare the index * to HEAD. (tree2 must be NULL in this case.) * - If tree1 is not NULL and tree2 is NULL, and index is FALSE, * then we compare the working directory to the tree1. * (repo must be NULL in this case.) * - If tree1 is not NULL and tree2 is NULL, and index is TRUE, * then we compare the index to tree1. (repo must be NULL.) * - If tree1 is not NULL and tree2 is not NULL, then we compare * tree1 to tree2. (repo must be NULL, index is ignored in this case). * * @param repo Repository. * @param tree1 The first tree to compare. * @param tree2 The second tree to compare. * @param index Whether to compare to the index. * @param filename Determines where to write the diff. If filename is * R_NilValue, then the diff is written to a S3 class git_diff * object. If filename is a character vector of length 0, then the * diff is written to a character vector. If filename is a character * vector of length one with non-NA value, the diff is written to a * file with name filename (the file is overwritten if it exists). * @param context_lines The number of unchanged lines that define the * boundary of a hunk (and to display before and after). * @param interhunk_lines The maximum number of unchanged lines * between hunk boundaries before the hunks will be merged into one. * @param old_prefix The virtual "directory" prefix for old file * names in hunk headers. * @param new_prefix The virtual "directory" prefix for new file * names in hunk headers. * @param id_abbrev The abbreviation length to use when formatting * object ids. Defaults to the value of 'core.abbrev' from the * config, or 7 if NULL. * @param path A character vector of paths / fnmatch patterns to * constrain diff. Default is NULL which include all paths. * @param max_size A size (in bytes) above which a blob will be * marked as binary automatically; pass a negative value to * disable. Defaults to 512MB when max_size is NULL. * @return A S3 class git_diff object if filename equals R_NilValue. A * character vector with diff if filename has length 0. Oterwise NULL. */ SEXP attribute_hidden git2r_diff( SEXP repo, SEXP tree1, SEXP tree2, SEXP index, SEXP filename, SEXP context_lines, SEXP interhunk_lines, SEXP old_prefix, SEXP new_prefix, SEXP id_abbrev, SEXP path, SEXP max_size) { int c_index; git_diff_options opts = GIT_DIFF_OPTIONS_INIT; if (git2r_arg_check_logical(index)) git2r_error(__func__, NULL, "'index'", git2r_err_logical_arg); c_index = LOGICAL(index)[0]; if (git2r_arg_check_integer_gte_zero(context_lines)) git2r_error(__func__, NULL, "'context_lines'", git2r_err_integer_gte_zero_arg); opts.context_lines = INTEGER(context_lines)[0]; if (git2r_arg_check_integer_gte_zero(interhunk_lines)) git2r_error(__func__, NULL, "'interhunk_lines'", git2r_err_integer_gte_zero_arg); opts.interhunk_lines = INTEGER(interhunk_lines)[0]; if (git2r_arg_check_string(old_prefix)) git2r_error(__func__, NULL, "'old_prefix'", git2r_err_string_arg); opts.old_prefix = CHAR(STRING_ELT(old_prefix, 0)); if (git2r_arg_check_string(new_prefix)) git2r_error(__func__, NULL, "'new_prefix'", git2r_err_string_arg); opts.new_prefix = CHAR(STRING_ELT(new_prefix, 0)); if (!Rf_isNull(id_abbrev)) { if (git2r_arg_check_integer_gte_zero(id_abbrev)) git2r_error(__func__, NULL, "'id_abbrev'", git2r_err_integer_gte_zero_arg); opts.id_abbrev = INTEGER(id_abbrev)[0]; } if (!Rf_isNull(path)) { int error; if (git2r_arg_check_string_vec(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_vec_arg); error = git2r_copy_string_vec(&(opts.pathspec), path); if (error || !opts.pathspec.count) { free(opts.pathspec.strings); git2r_error(__func__, git_error_last(), NULL, NULL); } } if (!Rf_isNull(max_size)) { if (git2r_arg_check_integer(max_size)) git2r_error(__func__, NULL, "'max_size'", git2r_err_integer_arg); opts.max_size = INTEGER(max_size)[0]; } if (Rf_isNull(tree1) && ! c_index) { if (!Rf_isNull(tree2)) git2r_error(__func__, NULL, git2r_err_diff_arg, NULL); return git2r_diff_index_to_wd(repo, filename, &opts); } if (Rf_isNull(tree1) && c_index) { if (!Rf_isNull(tree2)) git2r_error(__func__, NULL, git2r_err_diff_arg, NULL); return git2r_diff_head_to_index(repo, filename, &opts); } if (!Rf_isNull(tree1) && Rf_isNull(tree2) && !c_index) { if (!Rf_isNull(repo)) git2r_error(__func__, NULL, git2r_err_diff_arg, NULL); return git2r_diff_tree_to_wd(tree1, filename, &opts); } if (!Rf_isNull(tree1) && Rf_isNull(tree2) && c_index) { if (!Rf_isNull(repo)) git2r_error(__func__, NULL, git2r_err_diff_arg, NULL); return git2r_diff_tree_to_index(tree1, filename, &opts); } if (!Rf_isNull(repo)) git2r_error(__func__, NULL, git2r_err_diff_arg, NULL); return git2r_diff_tree_to_tree(tree1, tree2, filename, &opts); } static int git2r_diff_print_cb( const git_diff_delta *delta, const git_diff_hunk *hunk, const git_diff_line *line, void *payload) { int error; GIT2R_UNUSED(delta); GIT2R_UNUSED(hunk); if (line->origin == GIT_DIFF_LINE_CONTEXT || line->origin == GIT_DIFF_LINE_ADDITION || line->origin == GIT_DIFF_LINE_DELETION) { while ((error = fputc(line->origin, (FILE *)payload)) == EINTR) continue; if (error == EOF) return -1; } if (fwrite(line->content, line->content_len, 1, (FILE *)payload) != 1) return -1; return 0; } /** * Create a diff between the repository index and the workdir * directory. * * @param repo S3 class git_repository * @param filename Determines where to write the diff. If filename is * R_NilValue, then the diff is written to a S3 class git_diff * object. If filename is a character vector of length 0, then the * diff is written to a character vector. If filename is a character * vector of length one with non-NA value, the diff is written to a * file with name filename (the file is overwritten if it exists). * @param opts Structure describing options about how the diff * should be executed. * @return A S3 class git_diff object if filename equals R_NilValue. A * character vector with diff if filename has length 0. Oterwise NULL. */ SEXP attribute_hidden git2r_diff_index_to_wd( SEXP repo, SEXP filename, git_diff_options *opts) { int error, nprotect = 0; git_repository *repository = NULL; git_diff *diff = NULL; SEXP result = R_NilValue; if (git2r_arg_check_filename(filename)) git2r_error(__func__, NULL, "'filename'", git2r_err_filename_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_diff_index_to_workdir(&diff, repository, /*index=*/ NULL, opts); if (error) goto cleanup; if (Rf_isNull(filename)) { PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_diff)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_diff)); SET_VECTOR_ELT(result, git2r_S3_item__git_diff__old, Rf_mkString("index")); SET_VECTOR_ELT(result, git2r_S3_item__git_diff__new, Rf_mkString("workdir")); error = git2r_diff_format_to_r(diff, result); } else if (0 == Rf_length(filename)) { git_buf buf = GIT_BUF_INIT_CONST(NULL, 0); error = git_diff_to_buf(&buf, diff, GIT_DIFF_FORMAT_PATCH); if (!error) { PROTECT(result = Rf_mkString(buf.ptr)); nprotect++; } git_buf_dispose(&buf); } else { FILE *fp = fopen(CHAR(STRING_ELT(filename, 0)), "w+"); error = git_diff_print( diff, GIT_DIFF_FORMAT_PATCH, git2r_diff_print_cb, fp); if (fp) fclose(fp); } cleanup: free(opts->pathspec.strings); git_diff_free(diff); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Create a diff between head and repository index * * @param repo S3 class git_repository * @param filename Determines where to write the diff. If filename is * R_NilValue, then the diff is written to a S3 class git_diff * object. If filename is a character vector of length 0, then the * diff is written to a character vector. If filename is a character * vector of length one with non-NA value, the diff is written to a * file with name filename (the file is overwritten if it exists). * @param opts Structure describing options about how the diff * should be executed. * @return A S3 class git_diff object if filename equals R_NilValue. A * character vector with diff if filename has length 0. Oterwise NULL. */ SEXP attribute_hidden git2r_diff_head_to_index( SEXP repo, SEXP filename, git_diff_options *opts) { int error, nprotect = 0; git_repository *repository = NULL; git_diff *diff = NULL; git_object *obj = NULL; git_tree *head = NULL; SEXP result = R_NilValue; if (git2r_arg_check_filename(filename)) git2r_error(__func__, NULL, "'filename'", git2r_err_filename_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_revparse_single(&obj, repository, "HEAD^{tree}"); if (error) goto cleanup; error = git_tree_lookup(&head, repository, git_object_id(obj)); if (error) goto cleanup; error = git_diff_tree_to_index( &diff, repository, head, /* index= */ NULL, opts); if (error) goto cleanup; if (Rf_isNull(filename)) { /* TODO: object instead of HEAD string */ PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_diff)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_diff)); SET_VECTOR_ELT( result, git2r_S3_item__git_diff__old, Rf_mkString("HEAD")); SET_VECTOR_ELT( result, git2r_S3_item__git_diff__new, Rf_mkString("index")); error = git2r_diff_format_to_r(diff, result); } else if (0 == Rf_length(filename)) { git_buf buf = GIT_BUF_INIT_CONST(NULL, 0); error = git_diff_to_buf( &buf, diff, GIT_DIFF_FORMAT_PATCH); if (!error) { PROTECT(result = Rf_mkString(buf.ptr)); nprotect++; } git_buf_dispose(&buf); } else { FILE *fp = fopen(CHAR(STRING_ELT(filename, 0)), "w+"); error = git_diff_print( diff, GIT_DIFF_FORMAT_PATCH, git_diff_print_callback__to_file_handle, fp); if (fp) fclose(fp); } cleanup: free(opts->pathspec.strings); git_tree_free(head); git_object_free(obj); git_diff_free(diff); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Create a diff between a tree and the working directory * * @param tree S3 class git_tree * @param filename Determines where to write the diff. If filename is * R_NilValue, then the diff is written to a S3 class git_diff * object. If filename is a character vector of length 0, then the * diff is written to a character vector. If filename is a character * vector of length one with non-NA value, the diff is written to a * file with name filename (the file is overwritten if it exists). * @param opts Structure describing options about how the diff * should be executed. * @return A S3 class git_diff object if filename equals R_NilValue. A * character vector with diff if filename has length 0. Oterwise NULL. */ SEXP attribute_hidden git2r_diff_tree_to_wd( SEXP tree, SEXP filename, git_diff_options *opts) { int error, nprotect = 0; git_repository *repository = NULL; git_diff *diff = NULL; git_object *obj = NULL; git_tree *c_tree = NULL; SEXP sha; SEXP result = R_NilValue; SEXP repo; if (git2r_arg_check_tree(tree)) git2r_error(__func__, NULL, "'tree'", git2r_err_tree_arg); if (git2r_arg_check_filename(filename)) git2r_error(__func__, NULL, "'filename'", git2r_err_filename_arg); repo = git2r_get_list_element(tree, "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); sha = git2r_get_list_element(tree, "sha"); error = git_revparse_single(&obj, repository, CHAR(STRING_ELT(sha, 0))); if (error) goto cleanup; error = git_tree_lookup(&c_tree, repository, git_object_id(obj)); if (error) goto cleanup; error = git_diff_tree_to_workdir(&diff, repository, c_tree, opts); if (error) goto cleanup; if (Rf_isNull(filename)) { PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_diff)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_diff)); SET_VECTOR_ELT( result, git2r_S3_item__git_diff__old, tree); SET_VECTOR_ELT( result, git2r_S3_item__git_diff__new, Rf_mkString("workdir")); error = git2r_diff_format_to_r(diff, result); } else if (0 == Rf_length(filename)) { git_buf buf = GIT_BUF_INIT_CONST(NULL, 0); error = git_diff_to_buf( &buf, diff, GIT_DIFF_FORMAT_PATCH); if (!error) { PROTECT(result = Rf_mkString(buf.ptr)); nprotect++; } git_buf_dispose(&buf); } else { FILE *fp = fopen(CHAR(STRING_ELT(filename, 0)), "w+"); error = git_diff_print( diff, GIT_DIFF_FORMAT_PATCH, git_diff_print_callback__to_file_handle, fp); if (fp) fclose(fp); } cleanup: free(opts->pathspec.strings); git_diff_free(diff); git_tree_free(c_tree); git_object_free(obj); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Create a diff between a tree and repository index * * @param tree S3 class git_tree * @param filename Determines where to write the diff. If filename is * R_NilValue, then the diff is written to a S3 class git_diff * object. If filename is a character vector of length 0, then the * diff is written to a character vector. If filename is a character * vector of length one with non-NA value, the diff is written to a * file with name filename (the file is overwritten if it exists). * @param opts Structure describing options about how the diff * should be executed. * @return A S3 class git_diff object if filename equals R_NilValue. A * character vector with diff if filename has length 0. Oterwise NULL. */ SEXP attribute_hidden git2r_diff_tree_to_index( SEXP tree, SEXP filename, git_diff_options *opts) { int error, nprotect = 0; git_repository *repository = NULL; git_diff *diff = NULL; git_object *obj = NULL; git_tree *c_tree = NULL; SEXP sha; SEXP result = R_NilValue; SEXP repo; if (git2r_arg_check_tree(tree)) git2r_error(__func__, NULL, "'tree'", git2r_err_tree_arg); if (git2r_arg_check_filename(filename)) git2r_error(__func__, NULL, "'filename'", git2r_err_filename_arg); repo = git2r_get_list_element(tree, "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); sha = git2r_get_list_element(tree, "sha"); error = git_revparse_single(&obj, repository, CHAR(STRING_ELT(sha, 0))); if (error) goto cleanup; error = git_tree_lookup(&c_tree, repository, git_object_id(obj)); if (error) goto cleanup; error = git_diff_tree_to_index( &diff, repository, c_tree, /* index= */ NULL, opts); if (error) goto cleanup; if (Rf_isNull(filename)) { PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_diff)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_diff)); SET_VECTOR_ELT( result, git2r_S3_item__git_diff__old, tree); SET_VECTOR_ELT( result, git2r_S3_item__git_diff__new, Rf_mkString("index")); error = git2r_diff_format_to_r(diff, result); } else if (0 == Rf_length(filename)) { git_buf buf = GIT_BUF_INIT_CONST(NULL, 0); error = git_diff_to_buf( &buf, diff, GIT_DIFF_FORMAT_PATCH); if (!error) { PROTECT(result = Rf_mkString(buf.ptr)); nprotect++; } git_buf_dispose(&buf); } else { FILE *fp = fopen(CHAR(STRING_ELT(filename, 0)), "w+"); error = git_diff_print( diff, GIT_DIFF_FORMAT_PATCH, git_diff_print_callback__to_file_handle, fp); if (fp) fclose(fp); } cleanup: free(opts->pathspec.strings); git_diff_free(diff); git_tree_free(c_tree); git_object_free(obj); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Create a diff with the difference between two tree objects * * @param tree1 S3 class git_tree * @param tree2 S3 class git_tree * @param filename Determines where to write the diff. If filename is * R_NilValue, then the diff is written to a S3 class git_diff * object. If filename is a character vector of length 0, then the * diff is written to a character vector. If filename is a character * vector of length one with non-NA value, the diff is written to a * file with name filename (the file is overwritten if it exists). * @param opts Structure describing options about how the diff * should be executed. * @return A S3 class git_diff object if filename equals R_NilValue. A * character vector with diff if filename has length 0. Oterwise NULL. */ SEXP attribute_hidden git2r_diff_tree_to_tree( SEXP tree1, SEXP tree2, SEXP filename, git_diff_options *opts) { int error, nprotect = 0; git_repository *repository = NULL; git_diff *diff = NULL; git_object *obj1 = NULL, *obj2 = NULL; git_tree *c_tree1 = NULL, *c_tree2 = NULL; SEXP result = R_NilValue; SEXP tree1_repo, tree2_repo; SEXP sha1, sha2; if (git2r_arg_check_tree(tree1)) git2r_error(__func__, NULL, "'tree1'", git2r_err_tree_arg); if (git2r_arg_check_tree(tree2)) git2r_error(__func__, NULL, "'tree2'", git2r_err_tree_arg); if (git2r_arg_check_filename(filename)) git2r_error(__func__, NULL, "'filename'", git2r_err_filename_arg); tree1_repo = git2r_get_list_element(tree1, "repo"); tree2_repo = git2r_get_list_element(tree2, "repo"); if (git2r_arg_check_same_repo(tree1_repo, tree2_repo)) git2r_error(__func__, NULL, "'tree1' and 'tree2' not from same repository", NULL); repository = git2r_repository_open(tree1_repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); sha1 = git2r_get_list_element(tree1, "sha"); error = git_revparse_single(&obj1, repository, CHAR(STRING_ELT(sha1, 0))); if (error) goto cleanup; sha2 = git2r_get_list_element(tree2, "sha"); error = git_revparse_single(&obj2, repository, CHAR(STRING_ELT(sha2, 0))); if (error) goto cleanup; error = git_tree_lookup(&c_tree1, repository, git_object_id(obj1)); if (error) goto cleanup; error = git_tree_lookup(&c_tree2, repository, git_object_id(obj2)); if (error) goto cleanup; error = git_diff_tree_to_tree( &diff, repository, c_tree1, c_tree2, opts); if (error) goto cleanup; if (Rf_isNull(filename)) { PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_diff)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_diff)); SET_VECTOR_ELT( result, git2r_S3_item__git_diff__old, tree1); SET_VECTOR_ELT( result, git2r_S3_item__git_diff__new, tree2); error = git2r_diff_format_to_r(diff, result); } else if (0 == Rf_length(filename)) { git_buf buf = GIT_BUF_INIT_CONST(NULL, 0); error = git_diff_to_buf( &buf, diff, GIT_DIFF_FORMAT_PATCH); if (!error) { PROTECT(result = Rf_mkString(buf.ptr)); nprotect++; } git_buf_dispose(&buf); } else { FILE *fp = fopen(CHAR(STRING_ELT(filename, 0)), "w+"); error = git_diff_print( diff, GIT_DIFF_FORMAT_PATCH, git_diff_print_callback__to_file_handle, fp); if (fp) fclose(fp); } cleanup: free(opts->pathspec.strings); git_diff_free(diff); git_tree_free(c_tree1); git_tree_free(c_tree2); git_object_free(obj1); git_object_free(obj2); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Data structure to hold the information when counting diff objects. */ typedef struct { size_t num_files; size_t max_hunks; size_t max_lines; size_t num_hunks; size_t num_lines; } git2r_diff_count_payload; /** * Callback per file in the diff * * @param delta A pointer to the delta data for the file * @param progress Goes from 0 to 1 over the diff * @param payload A pointer to the git2r_diff_count_payload data structure * @return 0 */ static int git2r_diff_count_file_cb( const git_diff_delta *delta, float progress, void *payload) { git2r_diff_count_payload *n = payload; GIT2R_UNUSED(delta); GIT2R_UNUSED(progress); n->num_files += 1; n->num_hunks = n->num_lines = 0; return 0; } /** * Callback per hunk in the diff * * @param delta A pointer to the delta data for the file * @param hunk A pointer to the structure describing a hunk of a diff * @param payload A pointer to the git2r_diff_count_payload data structure * @return 0 */ static int git2r_diff_count_hunk_cb( const git_diff_delta *delta, const git_diff_hunk *hunk, void *payload) { git2r_diff_count_payload *n = payload; GIT2R_UNUSED(delta); GIT2R_UNUSED(hunk); n->num_hunks += 1; if (n->num_hunks > n->max_hunks) n->max_hunks = n->num_hunks; n->num_lines = 0; return 0; } /** * Callback per text diff line * * @param delta A pointer to the delta data for the file * @param hunk A pointer to the structure describing a hunk of a diff * @param line A pointer to the structure describing a line (or data * span) of a diff. * @param payload A pointer to the git2r_diff_count_payload data structure * @return 0 */ static int git2r_diff_count_line_cb( const git_diff_delta *delta, const git_diff_hunk *hunk, const git_diff_line *line, void *payload) { git2r_diff_count_payload *n = payload; GIT2R_UNUSED(delta); GIT2R_UNUSED(hunk); GIT2R_UNUSED(line); n->num_lines += 1; if (n->num_lines > n->max_lines) n->max_lines = n->num_lines; return 0; } /** * Count diff objects * * @param diff Pointer to the diff * @param num_files Pointer where to save the number of files * @param max_hunks Pointer where to save the maximum number of hunks * @param max_lines Pointer where to save the maximum number of lines * @return 0 if OK, else -1 */ static int git2r_diff_count( git_diff *diff, size_t *num_files, size_t *max_hunks, size_t *max_lines) { int error; git2r_diff_count_payload n = { 0, 0, 0 }; error = git_diff_foreach( diff, git2r_diff_count_file_cb, /* binary_cb */ NULL, git2r_diff_count_hunk_cb, git2r_diff_count_line_cb, /* payload= */ (void*) &n); if (error) return -1; *num_files = n.num_files; *max_hunks = n.max_hunks; *max_lines = n.max_lines; return 0; } /** * Data structure to hold the callback information when generating * diff objects. */ typedef struct { SEXP result; SEXP hunk_tmp; SEXP line_tmp; size_t file_ptr, hunk_ptr, line_ptr; } git2r_diff_payload; static int git2r_diff_get_hunk_cb( const git_diff_delta *delta, const git_diff_hunk *hunk, void *payload); static int git2r_diff_get_line_cb( const git_diff_delta *delta, const git_diff_hunk *hunk, const git_diff_line *line, void *payload); /** * Callback per file in the diff * * @param delta A pointer to the delta data for the file * @param progress Goes from 0 to 1 over the diff * @param payload A pointer to the git2r_diff_payload data structure * @return 0 */ static int git2r_diff_get_file_cb( const git_diff_delta *delta, float progress, void *payload) { git2r_diff_payload *p = (git2r_diff_payload *) payload; GIT2R_UNUSED(progress); /* Save previous hunk's lines in hunk_tmp, we just call the hunk callback, with a NULL hunk */ git2r_diff_get_hunk_cb(delta, /* hunk= */ 0, payload); /* Save the previous file's hunks from the hunk_tmp temporary storage. */ if (p->file_ptr != 0) { SEXP hunks; size_t len=p->hunk_ptr, i; SET_VECTOR_ELT( VECTOR_ELT(p->result, p->file_ptr - 1), git2r_S3_item__git_diff_file__hunks, hunks = Rf_allocVector(VECSXP, p->hunk_ptr)); for (i = 0; i < len ; i++) SET_VECTOR_ELT(hunks, i, VECTOR_ELT(p->hunk_tmp, i)); } /* OK, ready for next file, if any */ if (delta) { SEXP file_obj; PROTECT(file_obj = Rf_mkNamed(VECSXP, git2r_S3_items__git_diff_file)); Rf_setAttrib( file_obj, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_diff_file)); SET_VECTOR_ELT(p->result, p->file_ptr, file_obj); SET_VECTOR_ELT( file_obj, git2r_S3_item__git_diff_file__old_file, Rf_mkString(delta->old_file.path)); SET_VECTOR_ELT( file_obj, git2r_S3_item__git_diff_file__new_file, Rf_mkString(delta->new_file.path)); p->file_ptr++; p->hunk_ptr = 0; p->line_ptr = 0; UNPROTECT(1); } return 0; } /** * Process a hunk * * First we save the previous hunk, if there was one. Then create an * empty hunk (i.e. without any lines) and put it in the result. * * @param delta A pointer to the delta data for the file * @param hunk A pointer to the structure describing a hunk of a diff * @param payload Pointer to a git2r_diff_payload data structure * @return 0 */ static int git2r_diff_get_hunk_cb( const git_diff_delta *delta, const git_diff_hunk *hunk, void *payload) { git2r_diff_payload *p = (git2r_diff_payload *) payload; GIT2R_UNUSED(delta); /* Save previous hunk's lines in hunk_tmp, from the line_tmp temporary storage. */ if (p->hunk_ptr != 0) { SEXP lines; size_t len=p->line_ptr, i; SET_VECTOR_ELT( VECTOR_ELT(p->hunk_tmp, p->hunk_ptr-1), git2r_S3_item__git_diff_hunk__lines, lines = Rf_allocVector(VECSXP, p->line_ptr)); for (i = 0; i < len; i++) SET_VECTOR_ELT(lines, i, VECTOR_ELT(p->line_tmp, i)); } /* OK, ready for the next hunk, if any */ if (hunk) { SEXP hunk_obj; PROTECT(hunk_obj = Rf_mkNamed(VECSXP, git2r_S3_items__git_diff_hunk)); Rf_setAttrib( hunk_obj, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_diff_hunk)); SET_VECTOR_ELT( hunk_obj, git2r_S3_item__git_diff_hunk__old_start, Rf_ScalarInteger(hunk->old_start)); SET_VECTOR_ELT( hunk_obj, git2r_S3_item__git_diff_hunk__old_lines, Rf_ScalarInteger(hunk->old_lines)); SET_VECTOR_ELT( hunk_obj, git2r_S3_item__git_diff_hunk__new_start, Rf_ScalarInteger(hunk->new_start)); SET_VECTOR_ELT( hunk_obj, git2r_S3_item__git_diff_hunk__new_lines, Rf_ScalarInteger(hunk->new_lines)); SET_VECTOR_ELT( hunk_obj, git2r_S3_item__git_diff_hunk__header, Rf_mkString(hunk->header)); SET_VECTOR_ELT(p->hunk_tmp, p->hunk_ptr, hunk_obj); UNPROTECT(1); p->hunk_ptr += 1; p->line_ptr = 0; } return 0; } /** * Process a line * * This is easy, just populate a git_diff_line object and * put it in the temporary hunk. * * @param delta A pointer to the delta data for the file * @param hunk A pointer to the structure describing a hunk of a diff * @param line A pointer to the structure describing a line (or data * span) of a diff. * @param payload Pointer to a git2r_diff_payload data structure * @return 0 */ static int git2r_diff_get_line_cb( const git_diff_delta *delta, const git_diff_hunk *hunk, const git_diff_line *line, void *payload) { git2r_diff_payload *p = (git2r_diff_payload *) payload; static char short_buffer[200]; char *buffer = short_buffer; SEXP line_obj; GIT2R_UNUSED(delta); GIT2R_UNUSED(hunk); PROTECT(line_obj = Rf_mkNamed(VECSXP, git2r_S3_items__git_diff_line)); Rf_setAttrib( line_obj, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_diff_line)); SET_VECTOR_ELT( line_obj, git2r_S3_item__git_diff_line__origin, Rf_ScalarInteger(line->origin)); SET_VECTOR_ELT( line_obj, git2r_S3_item__git_diff_line__old_lineno, Rf_ScalarInteger(line->old_lineno)); SET_VECTOR_ELT( line_obj, git2r_S3_item__git_diff_line__new_lineno, Rf_ScalarInteger(line->new_lineno)); SET_VECTOR_ELT( line_obj, git2r_S3_item__git_diff_line__num_lines, Rf_ScalarInteger(line->num_lines)); if (line->content_len > sizeof(buffer)) buffer = malloc(line->content_len+1); memcpy(buffer, line->content, line->content_len); buffer[line->content_len] = 0; SET_VECTOR_ELT( line_obj, git2r_S3_item__git_diff_line__content, Rf_mkString(buffer)); if (buffer != short_buffer) free(buffer); SET_VECTOR_ELT(p->line_tmp, p->line_ptr++, line_obj); UNPROTECT(1); return 0; } /** * Format a diff as an R object * * libgit2 has callbacks to walk over the files, hunks and line * of a diff. This means that we need to walk over the diff twice, * if we don't want to reallocate our lists over and over again (or write a * smart list that preallocates memory). * * So we walk over it first and calculate the maximum number of * hunks in a file, and the maximum number of lines in a hunk. * * Then in the second walk, we have a correspondingly allocated * list that we use for temporary storage. * * @param diff Pointer to the diff * @param dest The S3 class git_diff to hold the formated diff * @return 0 if OK, else error code */ static int git2r_diff_format_to_r( git_diff *diff, SEXP dest) { int error, nprotect = 0; git2r_diff_payload payload = { /* result= */ R_NilValue, /* hunk_tmp= */ R_NilValue, /* line_tmp= */ R_NilValue, /* file_ptr= */ 0, /* hunk_ptr= */ 0, /* line_ptr= */ 0 }; size_t num_files, max_hunks, max_lines; error = git2r_diff_count(diff, &num_files, &max_hunks, &max_lines); if (error) return error; SET_VECTOR_ELT( dest, git2r_S3_item__git_diff__files, payload.result = Rf_allocVector(VECSXP, num_files)); PROTECT(payload.hunk_tmp = Rf_allocVector(VECSXP, max_hunks)); nprotect++; PROTECT(payload.line_tmp = Rf_allocVector(VECSXP, max_lines)); nprotect++; error = git_diff_foreach( diff, git2r_diff_get_file_cb, /* binary_cb */ NULL, git2r_diff_get_hunk_cb, git2r_diff_get_line_cb, &payload); if (!error) { /* Need to call them once more, to put in the last lines/hunks/files. */ error = git2r_diff_get_file_cb( /* delta= */ NULL, /* progress= */ 100, &payload); } if (nprotect) UNPROTECT(nprotect); return error; } git2r/src/git2r_config.c0000644000176200001440000003347014700530616014621 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_error.h" #include "git2r_repository.h" #define GIT2R_N_CONFIG_LEVELS 7 /** * Count number of config variables by level * * @param cfg where to count the variables * @param n_level array to store the number of variables * @param 0 on succes, or error code */ static int git2r_config_count_variables( const git_config *cfg, size_t *n_level) { int error; git_config_iterator *iterator = NULL; error = git_config_iterator_new(&iterator, cfg); if (error) return error; for (;;) { git_config_entry *entry; error = git_config_next(&entry, iterator); if (error) { if (GIT_ITEROVER == error) error = GIT_OK; goto cleanup; } switch (entry->level) { case GIT_CONFIG_LEVEL_PROGRAMDATA: n_level[0]++; break; case GIT_CONFIG_LEVEL_SYSTEM: n_level[1]++; break; case GIT_CONFIG_LEVEL_XDG: n_level[2]++; break; case GIT_CONFIG_LEVEL_GLOBAL: n_level[3]++; break; case GIT_CONFIG_LEVEL_LOCAL: n_level[4]++; break; case GIT_CONFIG_LEVEL_APP: n_level[5]++; break; case GIT_CONFIG_HIGHEST_LEVEL: n_level[6]++; break; default: giterr_set_str(GIT_ERROR_CONFIG, git2r_err_unexpected_config_level); error = GIT_ERROR; goto cleanup; } } cleanup: git_config_iterator_free(iterator); return error; } /** * Intialize a list for a config level. The list is only created if * there are any entries at that level. * * @param level the index of the level * @param n_level vector with number of entries per level * @param name name of the level to initialize * @return index of the config level list in the owning list */ static size_t git2r_config_list_init( SEXP list, size_t level, size_t *n_level, size_t *i_list, size_t i, const char *name) { if (n_level[level]) { SEXP item; SEXP names; i_list[level] = i++; SET_VECTOR_ELT( list, i_list[level], item = Rf_allocVector(VECSXP, n_level[level])); Rf_setAttrib(item, R_NamesSymbol, Rf_allocVector(STRSXP, n_level[level])); names = Rf_getAttrib(list, R_NamesSymbol); SET_STRING_ELT(names, i_list[level] , Rf_mkChar(name)); } return i; } /** * Add entry to result list. * * @param list the result list * @param level the level of the entry * @param i_level vector with the index where to add the entry within * the level * @param i_list vector with the index to the sub-list of the list at * level * @param entry the config entry to add * @return void */ static void git2r_config_list_add_entry( SEXP list, size_t level, size_t *i_level, size_t *i_list, git_config_entry *entry) { if (i_list[level] < (size_t)LENGTH(list)) { SEXP sub_list = VECTOR_ELT(list, i_list[level]); if (i_level[level] < (size_t)LENGTH(sub_list)) { SEXP names = Rf_getAttrib(sub_list, R_NamesSymbol); SET_STRING_ELT(names, i_level[level], Rf_mkChar(entry->name)); SET_VECTOR_ELT(sub_list, i_level[level], Rf_mkString(entry->value)); i_level[level]++; return; } } } /** * List config variables * * @param cfg Memory representation the configuration file for this * repository. * @param list The result list * @param n_level vector with number of entries per level * @return 0 if OK, else error code */ static int git2r_config_list_variables( git_config *cfg, SEXP list, size_t *n_level) { int error; size_t i_level[GIT2R_N_CONFIG_LEVELS] = {0}; /* Current index at level */ size_t i_list[GIT2R_N_CONFIG_LEVELS] = {0}; /* Index of level in target list */ git_config_iterator *iterator = NULL; size_t i = 0; error = git_config_iterator_new(&iterator, cfg); if (error) goto cleanup; i = git2r_config_list_init(list, 0, n_level, i_list, i, "programdata"); i = git2r_config_list_init(list, 1, n_level, i_list, i, "system"); i = git2r_config_list_init(list, 2, n_level, i_list, i, "xdg"); i = git2r_config_list_init(list, 3, n_level, i_list, i, "global"); i = git2r_config_list_init(list, 4, n_level, i_list, i, "local"); i = git2r_config_list_init(list, 5, n_level, i_list, i, "app"); i = git2r_config_list_init(list, 6, n_level, i_list, i, "highest"); for (;;) { git_config_entry *entry; error = git_config_next(&entry, iterator); if (error) { if (GIT_ITEROVER == error) error = GIT_OK; goto cleanup; } switch (entry->level) { case GIT_CONFIG_LEVEL_PROGRAMDATA: git2r_config_list_add_entry(list, 0, i_level, i_list, entry); break; case GIT_CONFIG_LEVEL_SYSTEM: git2r_config_list_add_entry(list, 1, i_level, i_list, entry); break; case GIT_CONFIG_LEVEL_XDG: git2r_config_list_add_entry(list, 2, i_level, i_list, entry); break; case GIT_CONFIG_LEVEL_GLOBAL: git2r_config_list_add_entry(list, 3, i_level, i_list, entry); break; case GIT_CONFIG_LEVEL_LOCAL: git2r_config_list_add_entry(list, 4, i_level, i_list, entry); break; case GIT_CONFIG_LEVEL_APP: git2r_config_list_add_entry(list, 5, i_level, i_list, entry); break; case GIT_CONFIG_HIGHEST_LEVEL: git2r_config_list_add_entry(list, 6, i_level, i_list, entry); break; default: giterr_set_str(GIT_ERROR_CONFIG, git2r_err_unexpected_config_level); error = GIT_ERROR; goto cleanup; } } cleanup: git_config_iterator_free(iterator); return error; } /** * Open configuration file * * @param out Pointer to store the loaded configuration. * @param repo S3 class git_repository. If non-R_NilValue open the * configuration file for the repository. If R_NilValue open the * global, XDG and system configuration files. * @param snapshot Open a snapshot of the configuration. * @return 0 on success, or an error code. */ static int git2r_config_open( git_config **out, SEXP repo, int snapshot) { int error; if (!Rf_isNull(repo)) { git_repository *repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); if (snapshot) error = git_repository_config_snapshot(out, repository); else error = git_repository_config(out, repository); git_repository_free(repository); } else if (snapshot) { git_config *config = NULL; error = git_config_open_default(&config); if (error) { git_config_free(config); return error; } error = git_config_snapshot(out, config); git_config_free(config); } else { error = git_config_open_default(out); } return error; } /** * Get config variables * * @param repo S3 class git_repository * @return VECSXP list with variables by level */ SEXP attribute_hidden git2r_config_get( SEXP repo) { int error, nprotect = 0; SEXP result = R_NilValue; size_t i = 0, n = 0, n_level[GIT2R_N_CONFIG_LEVELS] = {0}; git_config *cfg = NULL; error = git2r_config_open(&cfg, repo, 0); if (error) goto cleanup; error = git2r_config_count_variables(cfg, n_level); if (error) goto cleanup; /* Count levels with entries */ for (; i < GIT2R_N_CONFIG_LEVELS; i++) { if (n_level[i]) n++; } PROTECT(result = Rf_allocVector(VECSXP, n)); nprotect++; Rf_setAttrib(result, R_NamesSymbol, Rf_allocVector(STRSXP, n)); if (git2r_config_list_variables(cfg, result, n_level)) goto cleanup; cleanup: git_config_free(cfg); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Set or delete config entries * * @param repo S3 class git_repository * @param variables list of variables. If variable is NULL, it's deleted. * @return R_NilValue */ SEXP attribute_hidden git2r_config_set( SEXP repo, SEXP variables) { int error = 0, nprotect = 0; SEXP names; size_t i, n; git_config *cfg = NULL; if (git2r_arg_check_list(variables)) git2r_error(__func__, NULL, "'variables'", git2r_err_list_arg); n = Rf_length(variables); if (n) { error = git2r_config_open(&cfg, repo, 0); if (error) goto cleanup; PROTECT(names = Rf_getAttrib(variables, R_NamesSymbol)); nprotect++; for (i = 0; i < n; i++) { const char *key = CHAR(STRING_ELT(names, i)); const char *value = NULL; if (!Rf_isNull(VECTOR_ELT(variables, i))) value = CHAR(STRING_ELT(VECTOR_ELT(variables, i), 0)); if (value) error = git_config_set_string(cfg, key, value); else error = git_config_delete_entry(cfg, key); if (error) { if (error == GIT_EINVALIDSPEC) { Rf_warning("Variable was not in a valid format: '%s'", key); error = 0; } else { goto cleanup; } } } } cleanup: git_config_free(cfg); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Get the value of a string config variable * * @param repo S3 class git_repository * @param name The name of the variable * @return If the variable exists, a character vector of length one * with the value, else R_NilValue. */ SEXP attribute_hidden git2r_config_get_string( SEXP repo, SEXP name) { int error, nprotect = 0; SEXP result = R_NilValue; const char *value; git_config *cfg = NULL; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); error = git2r_config_open(&cfg, repo, 1); if (error) goto cleanup; error = git_config_get_string(&value, cfg, CHAR(STRING_ELT(name, 0))); if (error) { if (error == GIT_ENOTFOUND) error = 0; goto cleanup; } PROTECT(result = Rf_allocVector(STRSXP, 1)); nprotect++; SET_STRING_ELT(result, 0, Rf_mkChar(value)); cleanup: git_config_free(cfg); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Get the value of a boolean config variable * * @param repo S3 class git_repository * @param name The name of the variable * @return If the variable exists, a logical vector of length one * with TRUE or FALSE, else R_NilValue. */ SEXP attribute_hidden git2r_config_get_logical( SEXP repo, SEXP name) { int error, nprotect = 0; SEXP result = R_NilValue; int value; git_config *cfg = NULL; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); error = git2r_config_open(&cfg, repo, 1); if (error) goto cleanup; error = git_config_get_bool(&value, cfg, CHAR(STRING_ELT(name, 0))); if (error) { if (error == GIT_ENOTFOUND) error = 0; goto cleanup; } PROTECT(result = Rf_allocVector(LGLSXP, 1)); nprotect++; if (value) LOGICAL(result)[0] = 1; else LOGICAL(result)[0] = 0; cleanup: git_config_free(cfg); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Locate the path to the configuration file * * @return path if a configuration file has been found, else NA. */ SEXP attribute_hidden git2r_config_find_file( SEXP level) { int not_found = 1; SEXP result; git_buf buf = GIT_BUF_INIT_CONST(NULL, 0); if (git2r_arg_check_string(level)) git2r_error(__func__, NULL, "'level'", git2r_err_string_arg); if (strcmp(CHAR(STRING_ELT(level, 0)), "global") == 0) not_found = git_config_find_global(&buf); else if (strcmp(CHAR(STRING_ELT(level, 0)), "programdata") == 0) not_found = git_config_find_programdata(&buf); else if (strcmp(CHAR(STRING_ELT(level, 0)), "system") == 0) not_found = git_config_find_system(&buf); else if (strcmp(CHAR(STRING_ELT(level, 0)), "xdg") == 0) not_found = git_config_find_xdg(&buf); PROTECT(result = Rf_allocVector(STRSXP, 1)); if (not_found) SET_STRING_ELT(result, 0, NA_STRING); else SET_STRING_ELT(result, 0, Rf_mkChar(buf.ptr)); git_buf_dispose(&buf); UNPROTECT(1); return result; } git2r/src/git2r_push.c0000644000176200001440000000646714700264667014353 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_cred.h" #include "git2r_error.h" #include "git2r_push.h" #include "git2r_repository.h" #include "git2r_signature.h" #include "git2r_transfer.h" /** * Check if any non NA refspec * * @param refspec The string vector of refspec to push * @return 1 if nothing to push else 0 */ static int git2r_nothing_to_push( SEXP refspec) { size_t i, n; n = Rf_length(refspec); if (0 == n) return 1; /* Nothing to push */ for (i = 0; i < n; i++) { if (NA_STRING != STRING_ELT(refspec, i)) return 0; } /* Nothing to push */ return 1; } /** * Push * * @param repo S3 class git_repository * @param name The remote to push to * @param refspec The string vector of refspec to push * @param credentials The credentials for remote repository access. * @return R_NilValue */ SEXP attribute_hidden git2r_push( SEXP repo, SEXP name, SEXP refspec, SEXP credentials) { int error; git_remote *remote = NULL; git_repository *repository = NULL; git_strarray c_refspecs = {0}; git_push_options opts = GIT_PUSH_OPTIONS_INIT; git2r_transfer_data payload = GIT2R_TRANSFER_DATA_INIT; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); if (git2r_arg_check_string_vec(refspec)) git2r_error(__func__, NULL, "'refspec'", git2r_err_string_vec_arg); if (git2r_arg_check_credentials(credentials)) git2r_error(__func__, NULL, "'credentials'", git2r_err_credentials_arg); if (git2r_nothing_to_push(refspec)) return R_NilValue; repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_remote_lookup(&remote, repository, CHAR(STRING_ELT(name, 0))); if (error) goto cleanup; payload.credentials = credentials; opts.callbacks.payload = &payload; opts.callbacks.credentials = &git2r_cred_acquire_cb; error = git2r_copy_string_vec(&c_refspecs, refspec); if (error) goto cleanup; error = git_remote_push(remote, &c_refspecs, &opts); cleanup: free(c_refspecs.strings); if (remote) { if (git_remote_connected(remote)) git_remote_disconnect(remote); git_remote_free(remote); } git_repository_free(repository); if (error) git2r_error( __func__, git_error_last(), git2r_err_unable_to_authenticate, NULL); return R_NilValue; } git2r/src/git2r_repository.c0000644000176200001440000003761714700265012015575 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_blob.h" #include "git2r_branch.h" #include "git2r_commit.h" #include "git2r_error.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_signature.h" #include "git2r_tag.h" #include "git2r_tree.h" /** * Get repo from S3 class git_repository * * @param repo S3 class git_repository * @return a git_repository pointer on success else NULL */ attribute_hidden git_repository* git2r_repository_open( SEXP repo) { int error; SEXP path; git_repository *repository = NULL; if (git2r_arg_check_repository(repo)) { Rprintf("The repo argument is unexpectedly invalid\n"); return NULL; } path = git2r_get_list_element(repo, "path"); error = git_repository_open(&repository, CHAR(STRING_ELT(path, 0))); if (error) { if (error == GIT_ENOTFOUND) Rf_warning("Could not find repository at path '%s'", CHAR(STRING_ELT(path, 0))); else Rf_warning("Unable to open repository: %s", git_error_last()->message); git_repository_free(repository); return NULL; } return repository; } /** * Data structure to hold information when iterating over FETCH_HEAD * entries. */ typedef struct { size_t n; SEXP list; SEXP repo; } git2r_fetch_head_cb_data; /** * Invoked 'callback' for each entry in the given FETCH_HEAD file. * * @param ref_name The name of the ref. * @param remote_url The url of the remote. * @param oid The id of the remote head that were updated during the * last fetch. * @param is_merge Is head for merge. * @return 0 */ static int git2r_repository_fetchhead_foreach_cb( const char *ref_name, const char *remote_url, const git_oid *oid, unsigned int is_merge, void *payload) { git2r_fetch_head_cb_data *cb_data = (git2r_fetch_head_cb_data*)payload; /* Check if we have a list to populate */ if (!Rf_isNull(cb_data->list)) { char sha[GIT_OID_HEXSZ + 1]; SEXP fetch_head; PROTECT(fetch_head = Rf_mkNamed(VECSXP, git2r_S3_items__git_fetch_head)); Rf_setAttrib( fetch_head, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_fetch_head)); SET_VECTOR_ELT( fetch_head, git2r_S3_item__git_fetch_head__ref_name, Rf_mkString(ref_name)); SET_VECTOR_ELT( fetch_head, git2r_S3_item__git_fetch_head__remote_url, Rf_mkString(remote_url)); git_oid_tostr(sha, sizeof(sha), oid); SET_VECTOR_ELT( fetch_head, git2r_S3_item__git_fetch_head__sha, Rf_mkString(sha)); SET_VECTOR_ELT( fetch_head, git2r_S3_item__git_fetch_head__is_merge, Rf_ScalarLogical(is_merge)); SET_VECTOR_ELT( fetch_head, git2r_S3_item__git_fetch_head__repo, Rf_duplicate(cb_data->repo)); SET_VECTOR_ELT(cb_data->list, cb_data->n, fetch_head); UNPROTECT(1); } cb_data->n += 1; return 0; } /** * Get entries in FETCH_HEAD file * * @param repo S3 class git_repository * @return list with the S3 class git_fetch_head entries. R_NilValue * if there is no FETCH_HEAD file. */ SEXP attribute_hidden git2r_repository_fetch_heads( SEXP repo) { int error, nprotect = 0; SEXP result = R_NilValue; git2r_fetch_head_cb_data cb_data = {0, R_NilValue, R_NilValue}; git_repository *repository = NULL; repository= git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); /* Count number of fetch heads before creating the list */ error = git_repository_fetchhead_foreach( repository, git2r_repository_fetchhead_foreach_cb, &cb_data); if (error) { if (GIT_ENOTFOUND == error) error = GIT_OK; goto cleanup; } PROTECT(result = Rf_allocVector(VECSXP, cb_data.n)); nprotect++; cb_data.n = 0; cb_data.list = result; cb_data.repo = repo; error = git_repository_fetchhead_foreach( repository, git2r_repository_fetchhead_foreach_cb, &cb_data); cleanup: git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Get head of repository * * @param repo S3 class git_repository * @return R_NilValue if unborn branch or not found. S3 class * git_branch if not a detached head. S3 class git_commit if detached * head */ SEXP attribute_hidden git2r_repository_head( SEXP repo) { int error, nprotect = 0; SEXP result = R_NilValue; git_commit *commit = NULL; git_reference *reference = NULL; git_repository *repository = NULL; repository= git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_repository_head(&reference, repository); if (error) { if (GIT_EUNBORNBRANCH == error || GIT_ENOTFOUND == error) error = GIT_OK; goto cleanup; } if (git_reference_is_branch(reference)) { git_branch_t type = GIT_BRANCH_LOCAL; if (git_reference_is_remote(reference)) type = GIT_BRANCH_REMOTE; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_branch)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_branch)); error = git2r_branch_init(reference, type, repo, result); } else { error = git_commit_lookup( &commit, repository, git_reference_target(reference)); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_commit)); git2r_commit_init(commit, repo, result); } cleanup: git_commit_free(commit); git_reference_free(reference); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Init a repository. * * @param path A path to where to init a git repository * @param bare If TRUE, a Git repository without a working directory * is created at the pointed path. If FALSE, provided path will be * considered as the working directory into which the .git directory * will be created. * @param branch Use the specified name for the initial branch in the * newly created repository. If NULL, fall back to the default name. * @return R_NilValue */ SEXP attribute_hidden git2r_repository_init( SEXP path, SEXP bare, SEXP branch) { int error; git_repository *repository = NULL; git_repository_init_options opts = GIT_REPOSITORY_INIT_OPTIONS_INIT; if (git2r_arg_check_string(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_arg); if (git2r_arg_check_logical(bare)) git2r_error(__func__, NULL, "'bare'", git2r_err_logical_arg); if (!Rf_isNull(branch) && git2r_arg_check_string(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_string_arg); if (LOGICAL(bare)[0]) opts.flags |= GIT_REPOSITORY_INIT_BARE; if (!Rf_isNull(branch)) opts.initial_head = CHAR(STRING_ELT(branch, 0)); error = git_repository_init_ext(&repository, CHAR(STRING_ELT(path, 0)), &opts); if (error) git2r_error(__func__, NULL, git2r_err_repo_init, NULL); git_repository_free(repository); return R_NilValue; } /** * Check if repository is bare. * * @param repo S3 class git_repository * @return TRUE if bare else FALSE */ SEXP attribute_hidden git2r_repository_is_bare( SEXP repo) { int is_bare; git_repository *repository; repository= git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); is_bare = git_repository_is_bare(repository); git_repository_free(repository); if (is_bare < 0) git2r_error(__func__, git_error_last(), NULL, NULL); return Rf_ScalarLogical(is_bare); } /** * Determine if the repository was a shallow clone. * * @param repo S3 class git_repository * @return TRUE if shallow else FALSE */ SEXP attribute_hidden git2r_repository_is_shallow( SEXP repo) { int is_shallow; git_repository *repository; repository= git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); is_shallow = git_repository_is_shallow(repository); git_repository_free(repository); if (is_shallow < 0) git2r_error(__func__, git_error_last(), NULL, NULL); return Rf_ScalarLogical(is_shallow); } /** * Check if head of repository is detached * * @param repo S3 class git_repository * @return TRUE if detached else FALSE */ SEXP attribute_hidden git2r_repository_head_detached( SEXP repo) { int head_detached; git_repository *repository; repository= git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); head_detached = git_repository_head_detached(repository); git_repository_free(repository); if (head_detached < 0) git2r_error(__func__, git_error_last(), NULL, NULL); return Rf_ScalarLogical(head_detached); } /** * Check if repository is empty. * * @param repo S3 class git_repository * @return TRUE if empty else FALSE */ SEXP attribute_hidden git2r_repository_is_empty( SEXP repo) { int is_empty; git_repository *repository; repository= git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); is_empty = git_repository_is_empty(repository); git_repository_free(repository); if (is_empty < 0) git2r_error(__func__, git_error_last(), NULL, NULL); return Rf_ScalarLogical(is_empty); } /** * Check if valid repository. * * @param path The path to the potential repository * @return TRUE if the repository can be opened else FALSE */ SEXP attribute_hidden git2r_repository_can_open( SEXP path) { int error; git_repository *repository = NULL; if (git2r_arg_check_string(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_arg); error = git_repository_open(&repository, CHAR(STRING_ELT(path, 0))); git_repository_free(repository); if (error) return Rf_ScalarLogical(0); return Rf_ScalarLogical(1); } /** * Make the repository HEAD point to the specified reference. * * @param repo S3 class git_repository * @param ref_name Canonical name of the reference the HEAD should point at * @return R_NilValue */ SEXP attribute_hidden git2r_repository_set_head( SEXP repo, SEXP ref_name) { int error; git_repository *repository = NULL; if (git2r_arg_check_string(ref_name)) git2r_error(__func__, NULL, "'ref_name'", git2r_err_string_arg); if (!git_reference_is_valid_name(CHAR(STRING_ELT(ref_name, 0)))) git2r_error(__func__, NULL, git2r_err_invalid_refname, NULL); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_repository_set_head(repository, CHAR(STRING_ELT(ref_name, 0))); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Make the repository HEAD directly point to the commit. * * @param commit S3 class git_commit * @return R_NilValue */ SEXP attribute_hidden git2r_repository_set_head_detached( SEXP commit) { int error; SEXP sha; git_oid oid; git_commit *treeish = NULL; git_repository *repository = NULL; if (git2r_arg_check_commit(commit)) git2r_error(__func__, NULL, "'commit'", git2r_err_commit_arg); repository = git2r_repository_open(git2r_get_list_element(commit, "repo")); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); sha = git2r_get_list_element(commit, "sha"); error = git_oid_fromstr(&oid, CHAR(STRING_ELT(sha, 0))); if (error) goto cleanup; error = git_commit_lookup(&treeish, repository, &oid); if (error) goto cleanup; error = git_repository_set_head_detached( repository, git_commit_id(treeish)); cleanup: git_commit_free(treeish); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Get workdir of repository. * * @param repo S3 class git_repository * @return R_NilValue if bare repository, else character vector * of length one with path. */ SEXP attribute_hidden git2r_repository_workdir( SEXP repo) { int nprotect = 0; SEXP result = R_NilValue; git_repository *repository; repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); if (!git_repository_is_bare(repository)) { const char *wd = git_repository_workdir(repository); PROTECT(result = Rf_allocVector(STRSXP, 1)); nprotect++; SET_STRING_ELT(result, 0, Rf_mkChar(wd)); } git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); return result; } /** * Find repository base path for given path * * @param path A character vector specifying the path to a file or folder * @param ceiling The lookup will stop when this absolute path is reached. * @return R_NilValue if repository cannot be found or * a character vector of length one with path to repository's git dir * e.g. /path/to/my/repo/.git */ SEXP attribute_hidden git2r_repository_discover( SEXP path, SEXP ceiling) { int error, nprotect = 0; SEXP result = R_NilValue; git_buf buf = GIT_BUF_INIT_CONST(NULL, 0); const char *ceiling_dirs = NULL; if (git2r_arg_check_string(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_arg); if (!Rf_isNull(ceiling)) { if (git2r_arg_check_string(ceiling)) git2r_error(__func__, NULL, "'ceiling'", git2r_err_string_arg); ceiling_dirs = CHAR(STRING_ELT(ceiling, 0)); } /* note that across_fs (arg #3) is set to 0 so this will stop when * a filesystem device change is detected while exploring parent * directories */ error = git_repository_discover( &buf, CHAR(STRING_ELT(path, 0)), 0, ceiling_dirs); if (error) { /* NB just return R_NilValue if we can't discover the repo */ if (GIT_ENOTFOUND == error) error = GIT_OK; goto cleanup; } PROTECT(result = Rf_allocVector(STRSXP, 1)); nprotect++; SET_STRING_ELT(result, 0, Rf_mkChar(buf.ptr)); cleanup: git_buf_dispose(&buf); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } git2r/src/git2r_remote.c0000644000176200001440000003502214700530614014640 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_cred.h" #include "git2r_error.h" #include "git2r_remote.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_signature.h" #include "git2r_transfer.h" /** * Add a remote with the default fetch refspec to the repository's * configuration. * * @param repo S3 class git_repository * @param name The name of the remote * @param url The url of the remote * @return R_NilValue */ SEXP attribute_hidden git2r_remote_add( SEXP repo, SEXP name, SEXP url) { int error; git_repository *repository = NULL; git_remote *remote = NULL; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); if (git2r_arg_check_string(url)) git2r_error(__func__, NULL, "'url'", git2r_err_string_arg); if (!git_remote_is_valid_name(CHAR(STRING_ELT(name, 0)))) git2r_error(__func__, NULL, git2r_err_invalid_remote, NULL); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_remote_create( &remote, repository, CHAR(STRING_ELT(name, 0)), CHAR(STRING_ELT(url, 0))); git_remote_free(remote); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Each time a reference is updated locally, this function will be * called with information about it. * * Based on the libgit2 network/fetch.c example. * * @param refname The name of the remote * @param a The previous position of branch * @param b The new position of branch * @param payload Callback data. * @return 0 */ static int git2r_update_tips_cb( const char *refname, const git_oid *a, const git_oid *b, void *payload) { git2r_transfer_data *cb_data = (git2r_transfer_data*)payload; if (cb_data->verbose) { char b_str[GIT_OID_HEXSZ + 1]; git_oid_fmt(b_str, b); b_str[GIT_OID_HEXSZ] = '\0'; if (git_oid_is_zero(a)) { Rprintf("[new] %.20s %s\n", b_str, refname); } else { char a_str[GIT_OID_HEXSZ + 1]; git_oid_fmt(a_str, a); a_str[GIT_OID_HEXSZ] = '\0'; Rprintf("[updated] %.10s..%.10s %s\n", a_str, b_str, refname); } } return 0; } /** * Fetch new data and update tips * * @param repo S3 class git_repository * @param name The name of the remote to fetch from * @param credentials The credentials for remote repository access. * @param msg The one line long message to be appended to the reflog * @param verbose Print information each time a reference is updated locally. * @param refspecs The refspecs to use for this fetch. Pass R_NilValue * to use the base refspecs. * @return R_NilValue */ SEXP attribute_hidden git2r_remote_fetch( SEXP repo, SEXP name, SEXP credentials, SEXP msg, SEXP verbose, SEXP refspecs) { int error, nprotect = 0; SEXP result = R_NilValue; const git_indexer_progress *stats; git_remote *remote = NULL; git_repository *repository = NULL; git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT; git2r_transfer_data payload = GIT2R_TRANSFER_DATA_INIT; git_strarray refs = {0}; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); if (git2r_arg_check_credentials(credentials)) git2r_error(__func__, NULL, "'credentials'", git2r_err_credentials_arg); if (git2r_arg_check_string(msg)) git2r_error(__func__, NULL, "'msg'", git2r_err_string_arg); if (git2r_arg_check_logical(verbose)) git2r_error(__func__, NULL, "'verbose'", git2r_err_logical_arg); if ((!Rf_isNull(refspecs)) && git2r_arg_check_string_vec(refspecs)) git2r_error(__func__, NULL, "'refspecs'", git2r_err_string_vec_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_remote_lookup(&remote, repository, CHAR(STRING_ELT(name, 0))); if (error) goto cleanup; if (!Rf_isNull(refspecs)) { size_t i, len; /* Count number of non NA values */ len = Rf_length(refspecs); for (i = 0; i < len; i++) if (NA_STRING != STRING_ELT(refspecs, i)) refs.count++; if (refs.count) { /* Allocate the strings in refs */ refs.strings = malloc(refs.count * sizeof(char*)); if (!refs.strings) { giterr_set_str(GIT_ERROR_NONE, git2r_err_alloc_memory_buffer); error = GIT_ERROR; goto cleanup; } /* Populate the strings in refs */ for (i = 0; i < refs.count; i++) if (NA_STRING != STRING_ELT(refspecs, i)) refs.strings[i] = (char *)CHAR(STRING_ELT(refspecs, i)); } } if (LOGICAL(verbose)[0]) payload.verbose = 1; payload.credentials = credentials; fetch_opts.callbacks.payload = &payload; fetch_opts.callbacks.credentials = &git2r_cred_acquire_cb; fetch_opts.callbacks.update_tips = &git2r_update_tips_cb; error = git_remote_fetch(remote, &refs, &fetch_opts, CHAR(STRING_ELT(msg, 0))); if (error) goto cleanup; stats = git_remote_stats(remote); PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_transfer_progress)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_transfer_progress)); git2r_transfer_progress_init(stats, result); cleanup: free(refs.strings); if (remote && git_remote_connected(remote)) git_remote_disconnect(remote); git_remote_free(remote); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error( __func__, git_error_last(), git2r_err_unable_to_authenticate, NULL); return result; } /** * Get the configured remotes for a repo * * @param repo S3 class git_repository * @return Character vector with name of the remotes */ SEXP attribute_hidden git2r_remote_list( SEXP repo) { int error, nprotect = 0; size_t i; git_strarray rem_list; SEXP list = R_NilValue; git_repository *repository; repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_remote_list(&rem_list, repository); if (error) goto cleanup; PROTECT(list = Rf_allocVector(STRSXP, rem_list.count)); nprotect++; for (i = 0; i < rem_list.count; i++) SET_STRING_ELT(list, i, Rf_mkChar(rem_list.strings[i])); cleanup: git_strarray_free(&rem_list); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return list; } /** * Remove an existing remote * * All remote-tracking branches and configuration settings for the * remote will be removed. * @param repo S3 class git_repository * @param name The name of the remote to remove * @return R_NilValue */ SEXP attribute_hidden git2r_remote_remove( SEXP repo, SEXP name) { int error; git_repository *repository = NULL; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_remote_delete(repository, CHAR(STRING_ELT(name, 0))); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Give the remote a new name * * @param repo S3 class git_repository * @param oldname The old name of the remote * @param newname The new name of the remote * @return R_NilValue */ SEXP attribute_hidden git2r_remote_rename( SEXP repo, SEXP oldname, SEXP newname) { int error; git_strarray problems = {0}; git_repository *repository = NULL; if (git2r_arg_check_string(oldname)) git2r_error(__func__, NULL, "'oldname'", git2r_err_string_arg); if (git2r_arg_check_string(newname)) git2r_error(__func__, NULL, "'newname'", git2r_err_string_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_remote_rename( &problems, repository, CHAR(STRING_ELT(oldname, 0)), CHAR(STRING_ELT(newname, 0))); if (error) goto cleanup; git_strarray_free(&problems); cleanup: git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Set the remote's url in the configuration * * This assumes the common case of a single-url remote and * will otherwise raise an error. * @param repo S3 class git_repository * @param name The name of the remote * @param url The url to set * @return R_NilValue */ SEXP attribute_hidden git2r_remote_set_url( SEXP repo, SEXP name, SEXP url) { int error; git_repository *repository = NULL; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); if (git2r_arg_check_string(url)) git2r_error(__func__, NULL, "'url'", git2r_err_string_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_remote_set_url( repository, CHAR(STRING_ELT(name, 0)), CHAR(STRING_ELT(url, 0))); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Get the remote's url * * @param repo S3 class git_repository * @param remote Character vector with name of remote. NA values are * ok and give NA values as result at corresponding index in url * vector * @return Character vector with url for each remote */ SEXP attribute_hidden git2r_remote_url( SEXP repo, SEXP remote) { int error = GIT_OK; SEXP url; size_t len; size_t i = 0; git_remote *tmp_remote; git_repository *repository = NULL; if (git2r_arg_check_string_vec(remote)) git2r_error(__func__, NULL, "'remote'", git2r_err_string_vec_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); len = LENGTH(remote); PROTECT(url = Rf_allocVector(STRSXP, len)); for (; i < len; i++) { if (NA_STRING == STRING_ELT(remote, i)) { SET_STRING_ELT(url, i, NA_STRING); } else { error = git_remote_lookup( &tmp_remote, repository, CHAR(STRING_ELT(remote, i))); if (error) goto cleanup; SET_STRING_ELT(url, i, Rf_mkChar(git_remote_url(tmp_remote))); git_remote_free(tmp_remote); } } cleanup: git_repository_free(repository); UNPROTECT(1); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return url; } /** * Get the remote's url * * Based on https://github.com/libgit2/libgit2/blob/babdc376c7/examples/network/ls-remote.c * @param repo S3 class git_repository * @param name Character vector with URL of remote. * @return Character vector for each reference with the associated commit IDs. */ SEXP attribute_hidden git2r_remote_ls( SEXP name, SEXP repo, SEXP credentials) { const char *name_ = NULL; SEXP result = R_NilValue; SEXP names = R_NilValue; git_remote *remote = NULL; int error, nprotect = 0; const git_remote_head **refs; size_t refs_len, i; git_remote_callbacks callbacks = GIT_REMOTE_CALLBACKS_INIT; git2r_transfer_data payload = GIT2R_TRANSFER_DATA_INIT; git_repository *repository = NULL; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); if (git2r_arg_check_credentials(credentials)) git2r_error(__func__, NULL, "'credentials'", git2r_err_credentials_arg); if (!Rf_isNull(repo)) { repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); } name_ = CHAR(STRING_ELT(name, 0)); if (repository) { error = git_remote_lookup(&remote, repository, name_); if (error) { error = git_remote_create_anonymous(&remote, repository, name_); if (error) goto cleanup; } } else { error = git_remote_create_anonymous(&remote, repository, name_); if (error) goto cleanup; } payload.credentials = credentials; callbacks.payload = &payload; callbacks.credentials = &git2r_cred_acquire_cb; error = git_remote_connect(remote, GIT_DIRECTION_FETCH, &callbacks, NULL, NULL); if (error) goto cleanup; error = git_remote_ls(&refs, &refs_len, remote); if (error) goto cleanup; PROTECT(result = Rf_allocVector(STRSXP, refs_len)); nprotect++; Rf_setAttrib(result, R_NamesSymbol, names = Rf_allocVector(STRSXP, refs_len)); for (i = 0; i < refs_len; i++) { char oid[GIT_OID_HEXSZ + 1] = {0}; git_oid_fmt(oid, &refs[i]->oid); SET_STRING_ELT(result, i, Rf_mkChar(oid)); SET_STRING_ELT(names, i, Rf_mkChar(refs[i]->name)); } cleanup: git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } git2r/src/git2r_tree.c0000644000176200001440000001647214700261621014313 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_error.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_tree.h" /** * Init slots in S3 class git_tree * * @param source a tree * @param repo S3 class git_repository that contains the tree * @param dest S3 class git_tree to initialize * @return void */ void attribute_hidden git2r_tree_init( const git_tree *source, SEXP repo, SEXP dest) { SEXP filemode, id, type, name; int *filemode_ptr; size_t i, n; const git_oid *oid; char sha[GIT_OID_HEXSZ + 1]; const git_tree_entry *entry; oid = git_tree_id(source); git_oid_tostr(sha, sizeof(sha), oid); SET_VECTOR_ELT(dest, git2r_S3_item__git_tree__sha, Rf_mkString(sha)); n = git_tree_entrycount(source); SET_VECTOR_ELT( dest, git2r_S3_item__git_tree__filemode, filemode = Rf_allocVector(INTSXP, n)); SET_VECTOR_ELT( dest, git2r_S3_item__git_tree__id, id = Rf_allocVector(STRSXP, n)); SET_VECTOR_ELT( dest, git2r_S3_item__git_tree__type, type = Rf_allocVector(STRSXP, n)); SET_VECTOR_ELT( dest, git2r_S3_item__git_tree__name, name = Rf_allocVector(STRSXP, n)); filemode_ptr = INTEGER(filemode); for (i = 0; i < n; ++i) { entry = git_tree_entry_byindex(source, i); git_oid_tostr(sha, sizeof(sha), git_tree_entry_id(entry)); filemode_ptr[i] = git_tree_entry_filemode(entry); SET_STRING_ELT(id, i, Rf_mkChar(sha)); SET_STRING_ELT(type, i, Rf_mkChar(git_object_type2string(git_tree_entry_type(entry)))); SET_STRING_ELT(name, i, Rf_mkChar(git_tree_entry_name(entry))); } SET_VECTOR_ELT(dest, git2r_S3_item__git_tree__repo, Rf_duplicate(repo)); } /** * Data structure to hold information for the tree traversal. */ typedef struct { size_t n; SEXP list; int recursive; git_repository *repository; } git2r_tree_walk_cb_data; /** * Callback for the tree traversal method. * */ static int git2r_tree_walk_cb( const char *root, const git_tree_entry *entry, void *payload) { int error = 0; git2r_tree_walk_cb_data *p = (git2r_tree_walk_cb_data*)payload; if (p->recursive) { if (git_tree_entry_type(entry) != GIT_OBJECT_BLOB) return 0; } else if (*root) { return 1; } if (!Rf_isNull(p->list)) { char mode[23]; /* enums are int/32-bit, but this is enough for even a 64-bit int */ git_object *blob = NULL, *obj = NULL; char sha[GIT_OID_HEXSZ + 1]; /* mode */ error = snprintf(mode, sizeof(mode), "%06o", git_tree_entry_filemode(entry)); if (error < 0 || (size_t)error >= sizeof(mode)) { error = -1; goto cleanup; } SET_STRING_ELT(VECTOR_ELT(p->list, 0), p->n, Rf_mkChar(mode)); /* type */ SET_STRING_ELT(VECTOR_ELT(p->list, 1), p->n, Rf_mkChar(git_object_type2string(git_tree_entry_type(entry)))); /* sha */ git_oid_tostr(sha, sizeof(sha), git_tree_entry_id(entry)); SET_STRING_ELT(VECTOR_ELT(p->list, 2), p->n, Rf_mkChar(sha)); /* path */ SET_STRING_ELT(VECTOR_ELT(p->list, 3), p->n, Rf_mkChar(root)); /* name */ SET_STRING_ELT(VECTOR_ELT(p->list, 4), p->n, Rf_mkChar(git_tree_entry_name(entry))); /* length */ if (git_tree_entry_type(entry) == GIT_OBJECT_BLOB) { error = git_tree_entry_to_object(&obj, p->repository, entry); if (error) goto cleanup; error = git_object_peel(&blob, obj, GIT_OBJECT_BLOB); if (error) goto cleanup; INTEGER(VECTOR_ELT(p->list, 5))[p->n] = git_blob_rawsize((git_blob *)blob); } else { INTEGER(VECTOR_ELT(p->list, 5))[p->n] = NA_INTEGER; } cleanup: git_object_free(obj); git_object_free(blob); } p->n += 1; return error; } /** * Traverse the entries in a tree and its subtrees. * * @param tree S3 class git_tree * @param recursive recurse into sub-trees. * @return A list with entries */ SEXP attribute_hidden git2r_tree_walk( SEXP tree, SEXP recursive) { int error, nprotect = 0; git_oid oid; git_tree *tree_obj = NULL; git_repository *repository = NULL; git2r_tree_walk_cb_data cb_data = {0, R_NilValue}; SEXP repo = R_NilValue, sha = R_NilValue; SEXP result = R_NilValue, names = R_NilValue; if (git2r_arg_check_tree(tree)) git2r_error(__func__, NULL, "'tree'", git2r_err_tree_arg); if (git2r_arg_check_logical(recursive)) git2r_error(__func__, NULL, "'recursive'", git2r_err_logical_arg); repo = git2r_get_list_element(tree, "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); sha = git2r_get_list_element(tree, "sha"); git_oid_fromstr(&oid, CHAR(STRING_ELT(sha, 0))); error = git_tree_lookup(&tree_obj, repository, &oid); if (error) goto cleanup; /* Count number of entries before creating the list */ cb_data.repository = repository; if (LOGICAL(recursive)[0]) cb_data.recursive = 1; error = git_tree_walk(tree_obj, 0, &git2r_tree_walk_cb, &cb_data); if (error) goto cleanup; PROTECT(result = Rf_allocVector(VECSXP, 6)); nprotect++; Rf_setAttrib(result, R_NamesSymbol, names = Rf_allocVector(STRSXP, 6)); SET_VECTOR_ELT(result, 0, Rf_allocVector(STRSXP, cb_data.n)); SET_STRING_ELT(names, 0, Rf_mkChar("mode")); SET_VECTOR_ELT(result, 1, Rf_allocVector(STRSXP, cb_data.n)); SET_STRING_ELT(names, 1, Rf_mkChar("type")); SET_VECTOR_ELT(result, 2, Rf_allocVector(STRSXP, cb_data.n)); SET_STRING_ELT(names, 2, Rf_mkChar("sha")); SET_VECTOR_ELT(result, 3, Rf_allocVector(STRSXP, cb_data.n)); SET_STRING_ELT(names, 3, Rf_mkChar("path")); SET_VECTOR_ELT(result, 4, Rf_allocVector(STRSXP, cb_data.n)); SET_STRING_ELT(names, 4, Rf_mkChar("name")); SET_VECTOR_ELT(result, 5, Rf_allocVector(INTSXP, cb_data.n)); SET_STRING_ELT(names, 5, Rf_mkChar("len")); cb_data.list = result; cb_data.n = 0; error = git_tree_walk(tree_obj, 0, &git2r_tree_walk_cb, &cb_data); cleanup: git_repository_free(repository); git_tree_free(tree_obj); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } git2r/src/Makevars.in0000644000176200001440000000015714704123323014173 0ustar liggesusersPKG_CPPFLAGS = -DR_NO_REMAP -DSTRICT_R_HEADERS PKG_CFLAGS = @PKG_CFLAGS@ $(C_VISIBILITY) PKG_LIBS = @PKG_LIBS@ git2r/src/git2r_remote.h0000644000176200001440000000254213137360640014651 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_remote_h #define INCLUDE_git2r_remote_h #include #include SEXP git2r_remote_add(SEXP repo, SEXP name, SEXP url); SEXP git2r_remote_fetch( SEXP repo, SEXP name, SEXP credentials, SEXP msg, SEXP verbose, SEXP refspecs); SEXP git2r_remote_list(SEXP repo); SEXP git2r_remote_remove(SEXP repo, SEXP remote); SEXP git2r_remote_rename(SEXP repo, SEXP oldname, SEXP newname); SEXP git2r_remote_set_url(SEXP repo, SEXP name, SEXP url); SEXP git2r_remote_url(SEXP repo, SEXP remote); SEXP git2r_remote_ls(SEXP name, SEXP repo, SEXP credentials); #endif git2r/src/git2r_object.h0000644000176200001440000000163313226504307014623 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_object_h #define INCLUDE_git2r_object_h #include #include SEXP git2r_object_lookup(SEXP repo, SEXP sha); #endif git2r/src/git2r_revwalk.c0000644000176200001440000003557114700265072015034 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_commit.h" #include "git2r_error.h" #include "git2r_oid.h" #include "git2r_repository.h" #include "git2r_S3.h" /** * Count number of revisions. * * @param walker The walker to pop the commit from. * @param max_n n The upper limit of the number of commits to * output. Use max_n < 0 for unlimited number of commits. * @return The number of revisions */ static int git2r_revwalk_count( git_revwalk *walker, int max_n) { int n = 0; git_oid oid; while (!git_revwalk_next(&oid, walker)) { if (max_n < 0 || n < max_n) n++; else break; } return n; } /* Helper to find how many files in a commit changed from its nth * parent. */ static int git2r_match_with_parent( int *out, git_commit *commit, unsigned int i, git_diff_options *opts) { int error; git_commit *parent = NULL; git_tree *a = NULL, *b = NULL; git_diff *diff = NULL; if ((error = git_commit_parent(&parent, commit, i)) < 0) goto cleanup; if ((error = git_commit_tree(&a, parent)) < 0) goto cleanup; if ((error = git_commit_tree(&b, commit)) < 0) goto cleanup; if ((error = git_diff_tree_to_tree(&diff, git_commit_owner(commit), a, b, opts)) < 0) goto cleanup; *out = (git_diff_num_deltas(diff) > 0); cleanup: git_diff_free(diff); git_tree_free(a); git_tree_free(b); git_commit_free(parent); return error; } /** * List revisions * * @param repo S3 class git_repository * @param sha id of the commit to start from. * @param topological Sort the commits by topological order; Can be * combined with time. * @param time Sort the commits by commit time; can be combined with * topological. * @param reverse Sort the commits in reverse order * @param max_n n The upper limit of the number of commits to * output. Use max_n < 0 for unlimited number of commits. * @return list with S3 class git_commit objects */ SEXP attribute_hidden git2r_revwalk_list( SEXP repo, SEXP sha, SEXP topological, SEXP time, SEXP reverse, SEXP max_n) { int error = GIT_OK, nprotect = 0; SEXP result = R_NilValue; int i, n; unsigned int sort_mode = GIT_SORT_NONE; git_revwalk *walker = NULL; git_repository *repository = NULL; git_oid oid; if (git2r_arg_check_sha(sha)) git2r_error(__func__, NULL, "'sha'", git2r_err_sha_arg); if (git2r_arg_check_logical(topological)) git2r_error(__func__, NULL, "'topological'", git2r_err_logical_arg); if (git2r_arg_check_logical(time)) git2r_error(__func__, NULL, "'time'", git2r_err_logical_arg); if (git2r_arg_check_logical(reverse)) git2r_error(__func__, NULL, "'reverse'", git2r_err_logical_arg); if (git2r_arg_check_integer(max_n)) git2r_error(__func__, NULL, "'max_n'", git2r_err_integer_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); if (git_repository_is_empty(repository)) { /* No commits, create empty list */ PROTECT(result = Rf_allocVector(VECSXP, 0)); nprotect++; goto cleanup; } if (LOGICAL(topological)[0]) sort_mode |= GIT_SORT_TOPOLOGICAL; if (LOGICAL(time)[0]) sort_mode |= GIT_SORT_TIME; if (LOGICAL(reverse)[0]) sort_mode |= GIT_SORT_REVERSE; error = git_revwalk_new(&walker, repository); if (error) goto cleanup; git2r_oid_from_sha_sexp(sha, &oid); error = git_revwalk_push(walker, &oid); if (error) goto cleanup; git_revwalk_sorting(walker, sort_mode); /* Count number of revisions before creating the list */ n = git2r_revwalk_count(walker, INTEGER(max_n)[0]); /* Create list to store result */ PROTECT(result = Rf_allocVector(VECSXP, n)); nprotect++; git_revwalk_reset(walker); error = git_revwalk_push(walker, &oid); if (error) goto cleanup; git_revwalk_sorting(walker, sort_mode); for (i = 0; i < n; i++) { git_commit *commit; SEXP item; git_oid oid; error = git_revwalk_next(&oid, walker); if (error) { if (GIT_ITEROVER == error) error = GIT_OK; goto cleanup; } error = git_commit_lookup(&commit, repository, &oid); if (error) goto cleanup; SET_VECTOR_ELT( result, i, item = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); Rf_setAttrib(item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_commit)); git2r_commit_init(commit, repo, item); git_commit_free(commit); } cleanup: git_revwalk_free(walker); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * List revisions modifying a particular path. * * @param repo S3 class git_repository * @param sha id of the commit to start from. * @param topological Sort the commits by topological order; Can be * combined with time. * @param time Sort the commits by commit time; can be combined with * topological. * @param reverse Sort the commits in reverse order * @param max_n n The upper limit of the number of commits to * output. Use max_n < 0 for unlimited number of commits. * @param path Only commits modifying this path are selected * @return list with S3 class git_commit objects */ SEXP attribute_hidden git2r_revwalk_list2 ( SEXP repo, SEXP sha, SEXP topological, SEXP time, SEXP reverse, SEXP max_n, SEXP path) { int i = 0; int error = GIT_OK; int nprotect = 0; SEXP result = R_NilValue; int n; unsigned int sort_mode = GIT_SORT_NONE; git_revwalk *walker = NULL; git_repository *repository = NULL; git_oid oid; git_diff_options diffopts = GIT_DIFF_OPTIONS_INIT; git_pathspec *ps = NULL; if (git2r_arg_check_sha(sha)) git2r_error(__func__, NULL, "'sha'", git2r_err_sha_arg); if (git2r_arg_check_logical(topological)) git2r_error(__func__, NULL, "'topological'", git2r_err_logical_arg); if (git2r_arg_check_logical(time)) git2r_error(__func__, NULL, "'time'", git2r_err_logical_arg); if (git2r_arg_check_logical(reverse)) git2r_error(__func__, NULL, "'reverse'", git2r_err_logical_arg); if (git2r_arg_check_integer(max_n)) git2r_error(__func__, NULL, "'max_n'", git2r_err_integer_arg); if (git2r_arg_check_string(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_arg); /* Set up git pathspec. */ error = git2r_copy_string_vec(&(diffopts.pathspec), path); if (error || !diffopts.pathspec.count) goto cleanup; error = git_pathspec_new(&ps, &diffopts.pathspec); if (error) goto cleanup; /* Open the repository. */ repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); /* If there are no commits, create an empty list. */ if (git_repository_is_empty(repository)) { PROTECT(result = Rf_allocVector(VECSXP, 0)); nprotect++; goto cleanup; } if (LOGICAL(topological)[0]) sort_mode |= GIT_SORT_TOPOLOGICAL; if (LOGICAL(time)[0]) sort_mode |= GIT_SORT_TIME; if (LOGICAL(reverse)[0]) sort_mode |= GIT_SORT_REVERSE; /* Create a new "revwalker". */ error = git_revwalk_new(&walker, repository); if (error) goto cleanup; git2r_oid_from_sha_sexp(sha, &oid); error = git_revwalk_push(walker, &oid); if (error) goto cleanup; git_revwalk_sorting(walker, sort_mode); error = git_revwalk_push_head(walker); if (error) goto cleanup; n = Rf_asInteger(max_n); if (n < 0) { /* Count number of revisions before creating the list. */ n = git2r_revwalk_count(walker, n); } /* Restart the revwalker. */ git_revwalk_reset(walker); git_revwalk_sorting(walker, sort_mode); error = git_revwalk_push(walker, &oid); if (error) goto cleanup; /* Create the list to store the result. */ PROTECT(result = Rf_allocVector(VECSXP, n)); nprotect++; while (i < n) { git_commit *commit; SEXP item; git_oid oid; unsigned int parents, unmatched; int match; error = git_revwalk_next(&oid, walker); if (error) { if (GIT_ITEROVER == error) error = GIT_OK; goto cleanup; } error = git_commit_lookup(&commit, repository, &oid); if (error) goto cleanup; /* Check whether it is a "touching" commit---that is, a commit that has modified the selected path. */ parents = git_commit_parentcount(commit); unmatched = parents; if (parents == 0) { git_tree *tree; if ((error = git_commit_tree(&tree, commit)) < 0) { git_commit_free(commit); goto cleanup; } error = git_pathspec_match_tree( NULL, tree, GIT_PATHSPEC_NO_MATCH_ERROR, ps); git_tree_free(tree); if (error == GIT_ENOTFOUND) { error = 0; unmatched = 1; } else if (error < 0) { git_commit_free(commit); goto cleanup; } } else if (parents == 1) { if ((error = git2r_match_with_parent(&match, commit, 0, &diffopts)) < 0) { git_commit_free(commit); goto cleanup; } unmatched = match ? 0 : 1; } else { unsigned int j; for (j = 0; j < parents; j++) { if ((error = git2r_match_with_parent(&match, commit, j, &diffopts)) < 0) { git_commit_free(commit); goto cleanup; } if (match && unmatched) unmatched--; } } if (unmatched > 0) { git_commit_free(commit); continue; } SET_VECTOR_ELT( result, i, item = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); Rf_setAttrib(item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_commit)); git2r_commit_init(commit, repo, item); git_commit_free(commit); i++; } cleanup: free(diffopts.pathspec.strings); git_revwalk_free(walker); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Get list with contributions. * * @param repo S3 class git_repository * @param topological Sort the commits by topological order; Can be * combined with time. * @param time Sort the commits by commit time; can be combined with * topological. * @param reverse Sort the commits in reverse order * @return list with S3 class git_commit objects */ SEXP attribute_hidden git2r_revwalk_contributions( SEXP repo, SEXP topological, SEXP time, SEXP reverse) { int error = GIT_OK, nprotect = 0; SEXP result = R_NilValue; SEXP names = R_NilValue; SEXP when = R_NilValue; SEXP author = R_NilValue; SEXP email = R_NilValue; size_t i, n = 0; unsigned int sort_mode = GIT_SORT_NONE; git_revwalk *walker = NULL; git_repository *repository = NULL; if (git2r_arg_check_logical(topological)) git2r_error(__func__, NULL, "'topological'", git2r_err_logical_arg); if (git2r_arg_check_logical(time)) git2r_error(__func__, NULL, "'time'", git2r_err_logical_arg); if (git2r_arg_check_logical(reverse)) git2r_error(__func__, NULL, "'reverse'", git2r_err_logical_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); if (git_repository_is_empty(repository)) goto cleanup; if (LOGICAL(topological)[0]) sort_mode |= GIT_SORT_TOPOLOGICAL; if (LOGICAL(time)[0]) sort_mode |= GIT_SORT_TIME; if (LOGICAL(reverse)[0]) sort_mode |= GIT_SORT_REVERSE; error = git_revwalk_new(&walker, repository); if (error) goto cleanup; error = git_revwalk_push_head(walker); if (error) goto cleanup; git_revwalk_sorting(walker, sort_mode); /* Count number of revisions before creating the list */ n = git2r_revwalk_count(walker, -1); /* Create vectors to store result */ PROTECT(result = Rf_allocVector(VECSXP, 3)); nprotect++; Rf_setAttrib(result, R_NamesSymbol, names = Rf_allocVector(STRSXP, 3)); SET_VECTOR_ELT(result, 0, when = Rf_allocVector(REALSXP, n)); SET_STRING_ELT(names, 0, Rf_mkChar("when")); SET_VECTOR_ELT(result, 1, author = Rf_allocVector(STRSXP, n)); SET_STRING_ELT(names, 1, Rf_mkChar("author")); SET_VECTOR_ELT(result, 2, email = Rf_allocVector(STRSXP, n)); SET_STRING_ELT(names, 2, Rf_mkChar("email")); git_revwalk_reset(walker); error = git_revwalk_push_head(walker); if (error) goto cleanup; git_revwalk_sorting(walker, sort_mode); for (i = 0; i < n; i++) { git_commit *commit; const git_signature *c_author; git_oid oid; error = git_revwalk_next(&oid, walker); if (error) { if (GIT_ITEROVER == error) error = GIT_OK; goto cleanup; } error = git_commit_lookup(&commit, repository, &oid); if (error) goto cleanup; c_author = git_commit_author(commit); REAL(when)[i] = (double)(c_author->when.time) + 60.0 * (double)(c_author->when.offset); SET_STRING_ELT(author, i, Rf_mkChar(c_author->name)); SET_STRING_ELT(author, i, Rf_mkChar(c_author->email)); git_commit_free(commit); } cleanup: git_revwalk_free(walker); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } git2r/src/git2r_checkout.c0000644000176200001440000001035614700530617015160 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_checkout.h" #include "git2r_error.h" #include "git2r_repository.h" /** * Checkout path * * @param repo S3 class git_repository * @param path The paths to checkout * @return R_NilValue */ SEXP attribute_hidden git2r_checkout_path( SEXP repo, SEXP path) { int error = 0; size_t i, len; git_repository *repository = NULL; git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; if (git2r_arg_check_string_vec(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_vec_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); /* Count number of non NA values */ len = Rf_length(path); for (i = 0; i < len; i++) if (NA_STRING != STRING_ELT(path, i)) opts.paths.count++; /* We are done if no non-NA values */ if (!opts.paths.count) goto cleanup; /* Allocate the strings in pathspec */ opts.paths.strings = malloc(opts.paths.count * sizeof(char*)); if (!opts.paths.strings) { giterr_set_str(GIT_ERROR_NONE, git2r_err_alloc_memory_buffer); error = GIT_ERROR; goto cleanup; } /* Populate the strings in opts.paths */ for (i = 0; i < opts.paths.count; i++) if (NA_STRING != STRING_ELT(path, i)) opts.paths.strings[i] = (char *)CHAR(STRING_ELT(path, i)); opts.checkout_strategy = GIT_CHECKOUT_FORCE; error = git_checkout_head(repository, &opts); cleanup: free(opts.paths.strings); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Checkout tree * * @param repo S3 class git_repository * @param revision The revision string, see * http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions * @param force Using checkout strategy GIT_CHECKOUT_SAFE (force = * FALSE) or GIT_CHECKOUT_FORCE (force = TRUE). * @return R_NilValue */ SEXP attribute_hidden git2r_checkout_tree( SEXP repo, SEXP revision, SEXP force) { int error; git_repository *repository = NULL; git_object *treeish = NULL; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; if (git2r_arg_check_string(revision)) git2r_error(__func__, NULL, "'revision'", git2r_err_string_arg); if (git2r_arg_check_logical(force)) git2r_error(__func__, NULL, "'force'", git2r_err_logical_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_revparse_single(&treeish, repository, CHAR(STRING_ELT(revision, 0))); if (error) goto cleanup; switch (git_object_type(treeish)) { case GIT_OBJECT_COMMIT: case GIT_OBJECT_TAG: case GIT_OBJECT_TREE: error = GIT_OK; break; default: giterr_set_str(GIT_ERROR_NONE, git2r_err_checkout_tree); error = GIT_ERROR; break; } if (error) goto cleanup; if (LOGICAL(force)[0]) checkout_opts.checkout_strategy = GIT_CHECKOUT_FORCE; else checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; error = git_checkout_tree(repository, treeish, &checkout_opts); cleanup: git_object_free(treeish); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } git2r/src/git2r_commit.h0000644000176200001440000000231513273077667014663 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_commit_h #define INCLUDE_git2r_commit_h #include #include #include SEXP git2r_commit( SEXP repo, SEXP message, SEXP author, SEXP committer); int git2r_commit_lookup( git_commit **out, git_repository *repository, SEXP commit); SEXP git2r_commit_tree(SEXP commit); void git2r_commit_init(git_commit *source, SEXP repo, SEXP dest); SEXP git2r_commit_parent_list(SEXP commit); #endif git2r/src/git2r-win.def0000644000176200001440000000007013671131056014372 0ustar liggesusersLIBRARY git2r.dll EXPORTS R_init_git2r R_unload_git2r git2r/src/git2r_merge.h0000644000176200001440000000205013254030154014441 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2018 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_merge_h #define INCLUDE_git2r_merge_h #include #include SEXP git2r_merge_base(SEXP one, SEXP two); SEXP git2r_merge_branch(SEXP branch, SEXP merger, SEXP commit_on_success, SEXP fail); SEXP git2r_merge_fetch_heads(SEXP fetch_heads, SEXP merger); #endif git2r/src/git2r_S3.h0000644000176200001440000001554513453170501013646 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2018 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_S3_h #define INCLUDE_git2r_S3_h #include #include extern const char *git2r_S3_class__git_blame; extern const char *git2r_S3_items__git_blame[]; enum { git2r_S3_item__git_blame__path, git2r_S3_item__git_blame__hunks, git2r_S3_item__git_blame__repo}; extern const char *git2r_S3_class__git_blame_hunk; extern const char *git2r_S3_items__git_blame_hunk[]; enum { git2r_S3_item__git_blame_hunk__lines_in_hunk, git2r_S3_item__git_blame_hunk__final_commit_id, git2r_S3_item__git_blame_hunk__final_start_line_number, git2r_S3_item__git_blame_hunk__final_signature, git2r_S3_item__git_blame_hunk__orig_commit_id, git2r_S3_item__git_blame_hunk__orig_start_line_number, git2r_S3_item__git_blame_hunk__orig_signature, git2r_S3_item__git_blame_hunk__orig_path, git2r_S3_item__git_blame_hunk__boundary, git2r_S3_item__git_blame_hunk__repo}; extern const char *git2r_S3_class__git_blob; extern const char *git2r_S3_items__git_blob[]; enum { git2r_S3_item__git_blob__sha, git2r_S3_item__git_blob__repo}; extern const char *git2r_S3_class__git_branch; extern const char *git2r_S3_items__git_branch[]; enum { git2r_S3_item__git_branch__name, git2r_S3_item__git_branch__type, git2r_S3_item__git_branch__repo}; extern const char *git2r_S3_class__git_commit; extern const char *git2r_S3_items__git_commit[]; enum { git2r_S3_item__git_commit__sha, git2r_S3_item__git_commit__author, git2r_S3_item__git_commit__committer, git2r_S3_item__git_commit__summary, git2r_S3_item__git_commit__message, git2r_S3_item__git_commit__repo}; extern const char *git2r_S3_class__git_diff; extern const char *git2r_S3_items__git_diff[]; enum { git2r_S3_item__git_diff__old, git2r_S3_item__git_diff__new, git2r_S3_item__git_diff__files}; extern const char *git2r_S3_class__git_diff_file; extern const char *git2r_S3_items__git_diff_file[]; enum { git2r_S3_item__git_diff_file__old_file, git2r_S3_item__git_diff_file__new_file, git2r_S3_item__git_diff_file__hunks}; extern const char *git2r_S3_class__git_diff_hunk; extern const char *git2r_S3_items__git_diff_hunk[]; enum { git2r_S3_item__git_diff_hunk__old_start, git2r_S3_item__git_diff_hunk__old_lines, git2r_S3_item__git_diff_hunk__new_start, git2r_S3_item__git_diff_hunk__new_lines, git2r_S3_item__git_diff_hunk__header, git2r_S3_item__git_diff_hunk__lines}; extern const char *git2r_S3_class__git_diff_line; extern const char *git2r_S3_items__git_diff_line[]; enum { git2r_S3_item__git_diff_line__origin, git2r_S3_item__git_diff_line__old_lineno, git2r_S3_item__git_diff_line__new_lineno, git2r_S3_item__git_diff_line__num_lines, git2r_S3_item__git_diff_line__content}; extern const char *git2r_S3_class__git_fetch_head; extern const char *git2r_S3_items__git_fetch_head[]; enum { git2r_S3_item__git_fetch_head__ref_name, git2r_S3_item__git_fetch_head__remote_url, git2r_S3_item__git_fetch_head__sha, git2r_S3_item__git_fetch_head__is_merge, git2r_S3_item__git_fetch_head__repo}; extern const char *git2r_S3_class__git_merge_result; extern const char *git2r_S3_items__git_merge_result[]; enum { git2r_S3_item__git_merge_result__up_to_date, git2r_S3_item__git_merge_result__fast_forward, git2r_S3_item__git_merge_result__conflicts, git2r_S3_item__git_merge_result__sha}; extern const char *git2r_S3_class__git_note; extern const char *git2r_S3_items__git_note[]; enum { git2r_S3_item__git_note__sha, git2r_S3_item__git_note__annotated, git2r_S3_item__git_note__message, git2r_S3_item__git_note__refname, git2r_S3_item__git_note__repo}; extern const char *git2r_S3_class__git_reference; extern const char *git2r_S3_items__git_reference[]; enum { git2r_S3_item__git_reference__name, git2r_S3_item__git_reference__type, git2r_S3_item__git_reference__sha, git2r_S3_item__git_reference__target, git2r_S3_item__git_reference__shorthand, git2r_S3_item__git_reference__repo}; extern const char *git2r_S3_class__git_reflog_entry; extern const char *git2r_S3_items__git_reflog_entry[]; enum { git2r_S3_item__git_reflog_entry__sha, git2r_S3_item__git_reflog_entry__message, git2r_S3_item__git_reflog_entry__index, git2r_S3_item__git_reflog_entry__committer, git2r_S3_item__git_reflog_entry__refname, git2r_S3_item__git_reflog_entry__repo}; extern const char *git2r_S3_class__git_repository; extern const char *git2r_S3_items__git_repository[]; enum { git2r_S3_item__git_repository__path}; extern const char *git2r_S3_class__git_signature; extern const char *git2r_S3_items__git_signature[]; enum { git2r_S3_item__git_signature__name, git2r_S3_item__git_signature__email, git2r_S3_item__git_signature__when}; extern const char *git2r_S3_class__git_tag; extern const char *git2r_S3_items__git_tag[]; enum { git2r_S3_item__git_tag__sha, git2r_S3_item__git_tag__message, git2r_S3_item__git_tag__name, git2r_S3_item__git_tag__tagger, git2r_S3_item__git_tag__target, git2r_S3_item__git_tag__repo}; extern const char *git2r_S3_class__git_time; extern const char *git2r_S3_items__git_time[]; enum { git2r_S3_item__git_time__time, git2r_S3_item__git_time__offset}; extern const char *git2r_S3_class__git_transfer_progress; extern const char *git2r_S3_items__git_transfer_progress[]; enum { git2r_S3_item__git_transfer_progress__total_objects, git2r_S3_item__git_transfer_progress__indexed_objects, git2r_S3_item__git_transfer_progress__received_objects, git2r_S3_item__git_transfer_progress__local_objects, git2r_S3_item__git_transfer_progress__total_deltas, git2r_S3_item__git_transfer_progress__indexed_deltas, git2r_S3_item__git_transfer_progress__received_bytes}; extern const char *git2r_S3_class__git_tree; extern const char *git2r_S3_items__git_tree[]; enum { git2r_S3_item__git_tree__sha, git2r_S3_item__git_tree__filemode, git2r_S3_item__git_tree__type, git2r_S3_item__git_tree__id, git2r_S3_item__git_tree__name, git2r_S3_item__git_tree__repo}; SEXP git2r_get_list_element(SEXP list, const char *str); #endif git2r/src/git2r_arg.c0000644000176200001440000003003614700530073014115 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_error.h" #include "git2r_S3.h" /** * Check blob argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_blob( SEXP arg) { if (!Rf_isNewList(arg) || !Rf_inherits(arg, "git_blob")) return -1; if (git2r_arg_check_sha(git2r_get_list_element(arg, "sha"))) return -1; return 0; } /** * Check branch argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_branch( SEXP arg) { SEXP slot; if (!Rf_isNewList(arg) || !Rf_inherits(arg, "git_branch")) return -1; if (git2r_arg_check_string(git2r_get_list_element(arg, "name"))) return -1; slot = git2r_get_list_element(arg, "type"); if (git2r_arg_check_integer(slot)) return -1; switch (INTEGER(slot)[0]) { case GIT_BRANCH_LOCAL: case GIT_BRANCH_REMOTE: break; default: return -1; } return 0; } /** * Check commit argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_commit( SEXP arg) { if (!Rf_isNewList(arg) || !Rf_inherits(arg, "git_commit")) return -1; if (git2r_arg_check_sha(git2r_get_list_element(arg, "sha"))) return -1; return 0; } /** * Check commit or stash argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_commit_stash( SEXP arg) { if (!Rf_isNewList(arg)) return -1; if (!Rf_inherits(arg, "git_commit") && !Rf_inherits(arg, "git_stash")) return -1; if (git2r_arg_check_sha(git2r_get_list_element(arg, "sha"))) return -1; return 0; } /** * Check credentials argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_credentials( SEXP arg) { /* It's ok if the credentials is R_NilValue */ if (Rf_isNull(arg)) return 0; if (!Rf_isNewList(arg)) return -1; if (Rf_inherits(arg, "cred_env")) { /* Check username and password */ if (git2r_arg_check_string(git2r_get_list_element(arg, "username"))) return -1; if (git2r_arg_check_string(git2r_get_list_element(arg, "password"))) return -1; } else if (Rf_inherits(arg, "cred_token")) { /* Check token */ if (git2r_arg_check_string(git2r_get_list_element(arg, "token"))) return -1; } else if (Rf_inherits(arg, "cred_user_pass")) { /* Check username and password */ if (git2r_arg_check_string(git2r_get_list_element(arg, "username"))) return -1; if (git2r_arg_check_string(git2r_get_list_element(arg, "password"))) return -1; } else if (Rf_inherits(arg, "cred_ssh_key")) { SEXP passphrase; /* Check public and private key */ if (git2r_arg_check_string(git2r_get_list_element(arg, "publickey"))) return -1; if (git2r_arg_check_string(git2r_get_list_element(arg, "privatekey"))) return -1; /* Check that passphrase is a character vector */ passphrase = git2r_get_list_element(arg, "passphrase"); if (git2r_arg_check_string_vec(passphrase)) return -1; /* Check that length of passphrase < 2, i.e. it's either * character(0) or some "passphrase" */ switch (Rf_length(passphrase)) { case 0: break; case 1: if (NA_STRING == STRING_ELT(passphrase, 0)) return -1; break; default: return -1; } } else { return -1; } return 0; } /** * Check fetch_heads argument * * It's OK: * - A list with S3 class git_fetch_head objects * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_fetch_heads( SEXP arg) { const char *repo = NULL; size_t i,n; if (Rf_isNull(arg) || VECSXP != TYPEOF(arg)) return -1; /* Check that the repository paths are identical for each item */ n = Rf_length(arg); for (i = 0; i < n; i++) { SEXP path; SEXP item = VECTOR_ELT(arg, i); if (!Rf_isNewList(item) || !Rf_inherits(item, "git_fetch_head")) return -1; path = git2r_get_list_element(git2r_get_list_element(item, "repo"), "path"); if (git2r_arg_check_string(path)) return -1; if (0 == i) repo = CHAR(STRING_ELT(path, 0)); else if (0 != strcmp(repo, CHAR(STRING_ELT(path, 0)))) return -1; } return 0; } /** * Check filename argument * * It's OK: * - R_NilValue * - Zero length character vector * - character vector of length one with strlen(value) > 0 * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_filename( SEXP arg) { if (Rf_isNull(arg)) return 0; if (!Rf_isString(arg)) return -1; switch (Rf_length(arg)) { case 0: break; case 1: if (NA_STRING == STRING_ELT(arg, 0)) return -1; if (0 == strlen(CHAR(STRING_ELT(arg, 0)))) return -1; break; default: return -1; } return 0; } /** * Check sha argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_sha( SEXP arg) { size_t len; if (git2r_arg_check_string(arg)) return -1; len = LENGTH(STRING_ELT(arg, 0)); if (len < GIT_OID_MINPREFIXLEN || len > GIT_OID_HEXSZ) return -1; return 0; } /** * Check integer argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_integer( SEXP arg) { if (!Rf_isInteger(arg) || 1 != Rf_length(arg) || NA_INTEGER == INTEGER(arg)[0]) return -1; return 0; } /** * Check integer argument and that arg is greater than or equal to 0. * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_integer_gte_zero( SEXP arg) { if (git2r_arg_check_integer(arg)) return -1; if (0 > INTEGER(arg)[0]) return -1; return 0; } /** * Check list argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_list( SEXP arg) { if (!Rf_isNewList(arg)) return -1; return 0; } /** * Check logical argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_logical( SEXP arg) { if (!Rf_isLogical(arg) || 1 != Rf_length(arg) || NA_LOGICAL == LOGICAL(arg)[0]) return -1; return 0; } /** * Check note argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_note( SEXP arg) { if (!Rf_isNewList(arg) || !Rf_inherits(arg, "git_note")) return -1; if (git2r_arg_check_sha(git2r_get_list_element(arg, "sha"))) return -1; if (git2r_arg_check_string(git2r_get_list_element(arg, "refname"))) return -1; return 0; } /** * Check real argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_real( SEXP arg) { if (!Rf_isReal(arg) || 1 != Rf_length(arg) || !R_finite(REAL(arg)[0])) return -1; return 0; } /** * Check repository argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_repository( SEXP arg) { if (!Rf_isNewList(arg) || !Rf_inherits(arg, "git_repository")) return -1; if (git2r_arg_check_string(git2r_get_list_element(arg, "path"))) return -1; return 0; } /** * Check if the two repositories have the same path * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_same_repo( SEXP arg1, SEXP arg2) { SEXP path1, path2; if (git2r_arg_check_repository(arg1) || git2r_arg_check_repository(arg2)) return -1; path1 = git2r_get_list_element(arg1, "path"); path2 = git2r_get_list_element(arg2, "path"); if (strcmp(CHAR(STRING_ELT(path1, 0)), CHAR(STRING_ELT(path2, 0)))) return -1; return 0; } /** * Check signature argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_signature( SEXP arg) { SEXP when; if (!Rf_isNewList(arg) || !Rf_inherits(arg, "git_signature")) return -1; if (git2r_arg_check_string(git2r_get_list_element(arg, "name"))) return -1; if (git2r_arg_check_string(git2r_get_list_element(arg, "email"))) return -1; when = git2r_get_list_element(arg, "when"); if (git2r_arg_check_real(git2r_get_list_element(when, "time"))) return -1; if (git2r_arg_check_real(git2r_get_list_element(when, "offset"))) return -1; return 0; } /** * Check string argument * * Compared to git2r_arg_check_string_vec, also checks that length of vector * is one and non-NA. * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_string( SEXP arg) { if (git2r_arg_check_string_vec(arg) < 0) return -1; if (1 != Rf_length(arg) || NA_STRING == STRING_ELT(arg, 0)) return -1; return 0; } /** * Check string vector argument * * Compared to git2r_arg_check_string, only checks that argument is non-null * and string. Use git2r_arg_check_string to check scalar string. * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_string_vec( SEXP arg) { if (!Rf_isString(arg)) return -1; return 0; } /** * Copy SEXP character vector to git_strarray * * @param dst Destination of data * @src src Source of data. Skips NA strings. * @return 0 if OK, else error code */ int attribute_hidden git2r_copy_string_vec( git_strarray *dst, SEXP src) { size_t i, len; /* Count number of non NA values */ len = Rf_length(src); for (i = 0; i < len; i++) if (NA_STRING != STRING_ELT(src, i)) dst->count++; /* We are done if no non-NA values */ if (!dst->count) return 0; /* Allocate the strings in dst */ dst->strings = malloc(dst->count * sizeof(char*)); if (!dst->strings) { giterr_set_str(GIT_ERROR_NONE, git2r_err_alloc_memory_buffer); return GIT_ERROR; } /* Copy strings to dst */ for (i = 0; i < dst->count; i++) if (NA_STRING != STRING_ELT(src, i)) dst->strings[i] = (char *)CHAR(STRING_ELT(src, i)); return 0; } /** * Check tag argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_tag( SEXP arg) { if (!Rf_isNewList(arg) || !Rf_inherits(arg, "git_tag")) return -1; if (git2r_arg_check_string(git2r_get_list_element(arg, "target"))) return -1; return 0; } /** * Check tree argument * * @param arg the arg to check * @return 0 if OK, else -1 */ int attribute_hidden git2r_arg_check_tree( SEXP arg) { if (!Rf_isNewList(arg) || !Rf_inherits(arg, "git_tree")) return -1; if (git2r_arg_check_sha(git2r_get_list_element(arg, "sha"))) return -1; return 0; } git2r/src/git2r_oid.h0000644000176200001440000000165613273077667014155 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_oid_h #define INCLUDE_git2r_oid_h #include #include #include void git2r_oid_from_sha_sexp(SEXP sha, git_oid *oid); #endif git2r/src/git2r_object.c0000644000176200001440000000711314700264554014622 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_blob.h" #include "git2r_commit.h" #include "git2r_error.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_tag.h" #include "git2r_tree.h" /** * Lookup an object in a repository * * @param repo S3 class git_repository * @param sha 4 to 40 char hexadecimal string * @return S3 object with lookup */ SEXP attribute_hidden git2r_object_lookup( SEXP repo, SEXP sha) { int error, nprotect = 0; size_t len; SEXP result = R_NilValue; git_object *object = NULL; git_oid oid; git_repository *repository = NULL; if (git2r_arg_check_sha(sha)) git2r_error(__func__, NULL, "'sha'", git2r_err_sha_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); len = LENGTH(STRING_ELT(sha, 0)); if (GIT_OID_HEXSZ == len) { git_oid_fromstr(&oid, CHAR(STRING_ELT(sha, 0))); error = git_object_lookup(&object, repository, &oid, GIT_OBJECT_ANY); if (error) goto cleanup; } else { git_oid_fromstrn(&oid, CHAR(STRING_ELT(sha, 0)), len); error = git_object_lookup_prefix(&object, repository, &oid, len, GIT_OBJECT_ANY); if (error) goto cleanup; } switch (git_object_type(object)) { case GIT_OBJECT_COMMIT: PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_commit)); git2r_commit_init((git_commit*)object, repo, result); break; case GIT_OBJECT_TREE: PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_tree)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_tree)); git2r_tree_init((git_tree*)object, repo, result); break; case GIT_OBJECT_BLOB: PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_blob)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_blob)); git2r_blob_init((git_blob*)object, repo, result); break; case GIT_OBJECT_TAG: PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_tag)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_tag)); git2r_tag_init((git_tag*)object, repo, result); break; default: git2r_error(__func__, NULL, git2r_err_object_type, NULL); } cleanup: git_object_free(object); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } git2r/src/git2r_revparse.c0000644000176200001440000000726114700530577015210 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_blob.h" #include "git2r_commit.h" #include "git2r_error.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_tag.h" #include "git2r_tree.h" /** * Find object specified by revision * * @param repo S3 class git_repository * @param revision The revision string, see * http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions * @return S3 object of class git_commit, git_tag or git_tree. */ SEXP attribute_hidden git2r_revparse_single( SEXP repo, SEXP revision) { int error, nprotect = 0; SEXP result = R_NilValue; git_repository *repository = NULL; git_object *treeish = NULL; if (git2r_arg_check_string(revision)) git2r_error(__func__, NULL, "'revision'", git2r_err_string_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_revparse_single( &treeish, repository, CHAR(STRING_ELT(revision, 0))); if (error) goto cleanup; switch (git_object_type(treeish)) { case GIT_OBJECT_BLOB: PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_blob)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_blob)); git2r_blob_init((git_blob*)treeish, repo, result); break; case GIT_OBJECT_COMMIT: PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_commit)); git2r_commit_init((git_commit*)treeish, repo, result); break; case GIT_OBJECT_TAG: PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_tag)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_tag)); git2r_tag_init((git_tag*)treeish, repo, result); break; case GIT_OBJECT_TREE: PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_tree)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_tree)); git2r_tree_init((git_tree*)treeish, repo, result); break; default: giterr_set_str(GIT_ERROR_NONE, git2r_err_revparse_single); error = GIT_ERROR; break; } cleanup: git_object_free(treeish); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) { if (GIT_ENOTFOUND == error) { git2r_error( __func__, NULL, git2r_err_revparse_not_found, NULL); } else { git2r_error( __func__, git_error_last(), NULL, NULL); } } return result; } git2r/src/git2r_tag.c0000644000176200001440000002517314700265172014132 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_blob.h" #include "git2r_commit.h" #include "git2r_error.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_signature.h" #include "git2r_tag.h" #include "git2r_tree.h" /** * Init slots in S3 class git_tag * * @param source a tag * @param repo S3 class git_repository that contains the tag * @param dest S3 class git_tag to initialize * @return void */ void attribute_hidden git2r_tag_init( git_tag *source, SEXP repo, SEXP dest) { const git_signature *tagger; const git_oid *oid; char sha[GIT_OID_HEXSZ + 1]; char target[GIT_OID_HEXSZ + 1]; oid = git_tag_id(source); git_oid_tostr(sha, sizeof(sha), oid); SET_VECTOR_ELT(dest, git2r_S3_item__git_tag__sha, Rf_mkString(sha)); SET_VECTOR_ELT( dest, git2r_S3_item__git_tag__message, Rf_mkString(git_tag_message(source))); SET_VECTOR_ELT( dest, git2r_S3_item__git_tag__name, Rf_mkString(git_tag_name(source))); tagger = git_tag_tagger(source); if (tagger) { if (Rf_isNull(VECTOR_ELT(dest, git2r_S3_item__git_tag__tagger))) { SEXP item; SET_VECTOR_ELT( dest, git2r_S3_item__git_tag__tagger, item = Rf_mkNamed(VECSXP, git2r_S3_items__git_signature)); Rf_setAttrib(item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_signature)); } git2r_signature_init( tagger, VECTOR_ELT(dest, git2r_S3_item__git_tag__tagger)); } oid = git_tag_target_id(source); git_oid_tostr(target, sizeof(target), oid);; SET_VECTOR_ELT(dest, git2r_S3_item__git_tag__target, Rf_mkString(target)); SET_VECTOR_ELT(dest, git2r_S3_item__git_tag__repo, Rf_duplicate(repo)); } /** * Create tag targeting HEAD commit in repository. * * @param repo S3 class git_repository * @param name Name for the tag. * @param message The tag message. * @param tagger The tagger (author) of the tag * @param force Overwrite existing tag. * @return S3 object of class git_tag or git_commit */ SEXP attribute_hidden git2r_tag_create( SEXP repo, SEXP name, SEXP message, SEXP tagger, SEXP force) { SEXP result = R_NilValue; int error, nprotect = 0, overwrite = 0; git_oid oid; git_repository *repository = NULL; git_signature *sig_tagger = NULL; git_tag *tag = NULL; git_object *target = NULL; git_commit *commit = NULL; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); if (!Rf_isNull(message)) { if (git2r_arg_check_string(message)) git2r_error(__func__, NULL, "'message'", git2r_err_string_arg); if (git2r_arg_check_signature(tagger)) git2r_error(__func__, NULL, "'tagger'", git2r_err_signature_arg); } if (git2r_arg_check_logical(force)) git2r_error(__func__, NULL, "'force'", git2r_err_logical_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_revparse_single(&target, repository, "HEAD^{commit}"); if (error) goto cleanup; if (LOGICAL(force)[0]) overwrite = 1; if (Rf_isNull(message)) { error = git_tag_create_lightweight( &oid, repository, CHAR(STRING_ELT(name, 0)), target, overwrite); if (error) goto cleanup; error = git_commit_lookup(&commit, repository, &oid); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_commit)); git2r_commit_init(commit, repo, result); } else { error = git2r_signature_from_arg(&sig_tagger, tagger); if (error) goto cleanup; error = git_tag_create( &oid, repository, CHAR(STRING_ELT(name, 0)), target, sig_tagger, CHAR(STRING_ELT(message, 0)), overwrite); if (error) goto cleanup; error = git_tag_lookup(&tag, repository, &oid); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_tag)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_tag)); git2r_tag_init(tag, repo, result); } cleanup: git_commit_free(commit); git_tag_free(tag); git_signature_free(sig_tagger); git_object_free(target); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Delete an existing tag reference. * * @param repo S3 class git_repository * @param name Name of the tag to be deleted * @return R_NilValue */ SEXP attribute_hidden git2r_tag_delete( SEXP repo, SEXP name) { int error; git_repository *repository = NULL; if (git2r_arg_check_string(name)) git2r_error(__func__, NULL, "'name'", git2r_err_string_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_tag_delete(repository, CHAR(STRING_ELT(name, 0))); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Data structure to hold information when iterating over tags. */ typedef struct { size_t n; git_repository *repository; SEXP repo; SEXP tags; } git2r_tag_foreach_cb_data; /** * Invoked 'callback' for each tag * * @param name The name of the tag * @param oid The id of the tag * @param payload Payload data passed to 'git_tag_foreach' * @return 0 on success, else error code */ static int git2r_tag_foreach_cb( const char *name, git_oid *oid, void *payload) { int error = 0; git_object *object = NULL; git2r_tag_foreach_cb_data *cb_data = (git2r_tag_foreach_cb_data*)payload; /* Check if we have a list to populate */ if (!Rf_isNull(cb_data->tags)) { int skip = 0; SEXP item = R_NilValue, tag; error = git_object_lookup(&object, cb_data->repository, oid, GIT_OBJECT_ANY); if (error) goto cleanup; switch (git_object_type(object)) { case GIT_OBJECT_COMMIT: PROTECT(item = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); Rf_setAttrib( item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_commit)); git2r_commit_init((git_commit*)object, cb_data->repo, item); break; case GIT_OBJECT_TREE: PROTECT(item = Rf_mkNamed(VECSXP, git2r_S3_items__git_tree)); Rf_setAttrib( item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_tree)); git2r_tree_init((git_tree*)object, cb_data->repo, item); break; case GIT_OBJECT_BLOB: PROTECT(item = Rf_mkNamed(VECSXP, git2r_S3_items__git_blob)); Rf_setAttrib( item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_blob)); git2r_blob_init((git_blob*)object, cb_data->repo, item); break; case GIT_OBJECT_TAG: PROTECT(item = Rf_mkNamed(VECSXP, git2r_S3_items__git_tag)); Rf_setAttrib( item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_tag)); git2r_tag_init((git_tag*)object, cb_data->repo, item); break; default: git2r_error(__func__, NULL, git2r_err_object_type, NULL); } SET_VECTOR_ELT(cb_data->tags, cb_data->n, item); if (strncmp(name, "refs/tags/", sizeof("refs/tags/") - 1) == 0) skip = strlen("refs/tags/"); PROTECT(tag = Rf_mkChar(name + skip)); SET_STRING_ELT( Rf_getAttrib(cb_data->tags, R_NamesSymbol), cb_data->n, tag); UNPROTECT(2); if (object) git_object_free(object); object = NULL; } cb_data->n += 1; cleanup: git_object_free(object); return error; } /** * Get all tags that can be found in a repository. * * @param repo S3 class git_repository * @return VECXSP with S3 objects of class git_tag */ SEXP attribute_hidden git2r_tag_list( SEXP repo) { int error, nprotect = 0; SEXP result = R_NilValue; git2r_tag_foreach_cb_data cb_data = {0, NULL, R_NilValue, R_NilValue}; git_repository *repository; repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); /* Count number of tags before creating the list */ error = git_tag_foreach(repository, &git2r_tag_foreach_cb, &cb_data); if (error) { if (GIT_ENOTFOUND == error) { error = 0; PROTECT(result = Rf_allocVector(VECSXP, 0)); nprotect++; Rf_setAttrib(result, R_NamesSymbol, Rf_allocVector(STRSXP, 0)); } goto cleanup; } PROTECT(result = Rf_allocVector(VECSXP, cb_data.n)); nprotect++; Rf_setAttrib(result, R_NamesSymbol, Rf_allocVector(STRSXP, cb_data.n)); cb_data.n = 0; cb_data.tags = result; cb_data.repo = repo; cb_data.repository = repository; error = git_tag_foreach(repository, &git2r_tag_foreach_cb, &cb_data); cleanup: git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } git2r/src/git2r_push.h0000644000176200001440000000165713137360640014343 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_push_h #define INCLUDE_git2r_push_h #include #include SEXP git2r_push(SEXP repo, SEXP name, SEXP refspec, SEXP credentials); #endif git2r/src/git2r_tag.h0000644000176200001440000000212613453665310014132 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2019 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_tag_h #define INCLUDE_git2r_tag_h #include #include #include void git2r_tag_init(git_tag *source, SEXP repo, SEXP dest); SEXP git2r_tag_create(SEXP repo, SEXP name, SEXP message, SEXP tagger, SEXP force); SEXP git2r_tag_delete(SEXP repo, SEXP name); SEXP git2r_tag_list(SEXP repo); #endif git2r/src/git2r_reflog.c0000644000176200001440000001102514700264733014626 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_error.h" #include "git2r_reflog.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_signature.h" /** * Init slots in S3 class git_reflog_entry * * @param source The source reflog entry * @param index The entry index * @param repo S3 class git_repository * @param ref Reference to read from * @param dest S3 class git_reflog_entry to initialize * @return void */ static void git2r_reflog_entry_init( const git_reflog_entry *source, size_t index, SEXP repo, SEXP ref, SEXP dest) { SEXP i; const char *message; const git_signature *committer; char sha[GIT_OID_HEXSZ + 1]; git_oid_fmt(sha, git_reflog_entry_id_new(source)); sha[GIT_OID_HEXSZ] = '\0'; SET_VECTOR_ELT( dest, git2r_S3_item__git_reflog_entry__sha, Rf_mkString(sha)); SET_VECTOR_ELT( dest, git2r_S3_item__git_reflog_entry__index, i = Rf_allocVector(INTSXP, 1)); INTEGER(i)[0] = index; committer = git_reflog_entry_committer(source); if (committer) { if (Rf_isNull(VECTOR_ELT(dest, git2r_S3_item__git_reflog_entry__committer))) { SEXP item; SET_VECTOR_ELT( dest, git2r_S3_item__git_reflog_entry__committer, item = Rf_mkNamed(VECSXP, git2r_S3_items__git_signature)); Rf_setAttrib(item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_signature)); } git2r_signature_init( committer, VECTOR_ELT(dest, git2r_S3_item__git_reflog_entry__committer)); } message = git_reflog_entry_message(source); if (message) { SET_VECTOR_ELT( dest, git2r_S3_item__git_reflog_entry__message, Rf_mkString(message)); } else { SET_VECTOR_ELT( dest, git2r_S3_item__git_reflog_entry__message, Rf_ScalarString(NA_STRING)); } SET_VECTOR_ELT( dest, git2r_S3_item__git_reflog_entry__refname, ref); SET_VECTOR_ELT( dest, git2r_S3_item__git_reflog_entry__repo, Rf_duplicate(repo)); } /** * List the reflog within a specified reference. * * @param repo S3 class git_repository * @param ref Reference to read from. * @return VECXSP with S3 objects of class git_reflog */ SEXP attribute_hidden git2r_reflog_list( SEXP repo, SEXP ref) { int error, nprotect = 0; size_t i, n; SEXP result = R_NilValue; git_reflog *reflog = NULL; git_repository *repository = NULL; if (git2r_arg_check_string(ref)) git2r_error(__func__, NULL, "'ref'", git2r_err_string_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_reflog_read(&reflog, repository, CHAR(STRING_ELT(ref, 0))); if (error) goto cleanup; n = git_reflog_entrycount(reflog); PROTECT(result = Rf_allocVector(VECSXP, n)); nprotect++; for (i = 0; i < n; i++) { const git_reflog_entry *entry = git_reflog_entry_byindex(reflog, i); if (entry) { SEXP item; SET_VECTOR_ELT( result, i, item = Rf_mkNamed(VECSXP, git2r_S3_items__git_reflog_entry)); Rf_setAttrib(item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_reflog_entry)); git2r_reflog_entry_init(entry, i, repo, ref, item); } } cleanup: git_reflog_free(reflog); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } git2r/src/git2r_diff.h0000644000176200001440000000206613436723525014276 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2019 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_diff_h #define INCLUDE_git2r_diff_h SEXP git2r_diff( SEXP repo, SEXP tree1, SEXP tree2, SEXP index, SEXP filename, SEXP context_lines, SEXP interhunk_lines, SEXP old_prefix, SEXP new_prefix, SEXP id_abbrev, SEXP path, SEXP max_size); #endif git2r/src/git2r_checkout.h0000644000176200001440000000174013137360640015162 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_checkout_h #define INCLUDE_git2r_checkout_h #include #include SEXP git2r_checkout_path(SEXP repo, SEXP path); SEXP git2r_checkout_tree(SEXP repo, SEXP revision, SEXP force); #endif git2r/src/git2r_revparse.h0000644000176200001440000000164613137360640015211 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_revparse_h #define INCLUDE_git2r_revparse_h #include #include SEXP git2r_revparse_single(SEXP repo, SEXP revision); #endif git2r/src/git2r_index.h0000644000176200001440000000173413137360640014467 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_index_h #define INCLUDE_git2r_index_h #include #include SEXP git2r_index_add_all(SEXP repo, SEXP path, SEXP force); SEXP git2r_index_remove_bypath(SEXP repo, SEXP path); #endif git2r/src/git2r_reset.h0000644000176200001440000000171213137360640014476 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2016 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_reset_h #define INCLUDE_git2r_reset_h #include #include SEXP git2r_reset(SEXP commit, SEXP reset_type); SEXP git2r_reset_default(SEXP repo, SEXP path); #endif git2r/src/git2r_config.h0000644000176200001440000000212213254030154014607 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2018 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_config_h #define INCLUDE_git2r_config_h #include #include SEXP git2r_config_find_file(SEXP level); SEXP git2r_config_get(SEXP repo); SEXP git2r_config_get_logical(SEXP repo, SEXP name); SEXP git2r_config_get_string(SEXP repo, SEXP name); SEXP git2r_config_set(SEXP repo, SEXP variables); #endif git2r/src/git2r_index.c0000644000176200001440000000704214700262135014455 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_error.h" #include "git2r_index.h" #include "git2r_repository.h" /** * Add or update index entries matching files in the working * directory. * * @param repo S3 class git_repository * @param path array of path patterns * @param force if TRUE, add ignored files. * @return R_NilValue */ SEXP attribute_hidden git2r_index_add_all( SEXP repo, SEXP path, SEXP force) { int error = 0; unsigned int flags = 0; git_strarray pathspec = {0}; git_index *index = NULL; git_repository *repository = NULL; if (git2r_arg_check_string_vec(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_vec_arg); if (git2r_arg_check_logical(force)) git2r_error(__func__, NULL, "'force'", git2r_err_logical_arg); repository= git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git2r_copy_string_vec(&pathspec, path); if (error || !pathspec.count) goto cleanup; error = git_repository_index(&index, repository); if (error) goto cleanup; if (LOGICAL(force)[0]) flags |= GIT_INDEX_ADD_FORCE; error = git_index_add_all(index, &pathspec, flags, NULL, NULL); if (error) goto cleanup; error = git_index_write(index); cleanup: free(pathspec.strings); git_index_free(index); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } /** * Remove an index entry corresponding to a file relative to the * repository's working folder. * * @param repo S3 class git_repository * @param path array of path patterns * @return R_NilValue */ SEXP attribute_hidden git2r_index_remove_bypath( SEXP repo, SEXP path) { int error = 0; size_t i, len; git_index *index = NULL; git_repository *repository = NULL; if (git2r_arg_check_string_vec(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_vec_arg); len = Rf_length(path); if (!len) goto cleanup; repository= git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_repository_index(&index, repository); if (error) goto cleanup; for (i = 0; i < len; i++) { if (NA_STRING != STRING_ELT(path, i)) { error = git_index_remove_bypath(index, CHAR(STRING_ELT(path, i))); if (error) goto cleanup; } } error = git_index_write(index); cleanup: git_index_free(index); git_repository_free(repository); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return R_NilValue; } git2r/src/git2r.c0000644000176200001440000001327614704013416013274 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2019 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /** @file git2r.c * @brief R bindings to the libgit2 library * * These functions are called from R with .Call to interface the * libgit2 library from R. * */ #include "git2r_arg.h" #include "git2r_blame.h" #include "git2r_blob.h" #include "git2r_branch.h" #include "git2r_checkout.h" #include "git2r_clone.h" #include "git2r_config.h" #include "git2r_commit.h" #include "git2r_diff.h" #include "git2r_error.h" #include "git2r_graph.h" #include "git2r_index.h" #include "git2r_libgit2.h" #include "git2r_merge.h" #include "git2r_note.h" #include "git2r_object.h" #include "git2r_odb.h" #include "git2r_push.h" #include "git2r_reference.h" #include "git2r_reflog.h" #include "git2r_remote.h" #include "git2r_repository.h" #include "git2r_reset.h" #include "git2r_revparse.h" #include "git2r_revwalk.h" #include "git2r_signature.h" #include "git2r_stash.h" #include "git2r_status.h" #include "git2r_tag.h" #include "git2r_tree.h" #include #include #define CALLDEF(name, n) {#name, (DL_FUNC) &name, n} static const R_CallMethodDef callMethods[] = { CALLDEF(git2r_blame_file, 2), CALLDEF(git2r_blob_content, 2), CALLDEF(git2r_blob_create_fromdisk, 2), CALLDEF(git2r_blob_create_fromworkdir, 2), CALLDEF(git2r_blob_is_binary, 1), CALLDEF(git2r_blob_rawsize, 1), CALLDEF(git2r_branch_canonical_name, 1), CALLDEF(git2r_branch_create, 3), CALLDEF(git2r_branch_delete, 1), CALLDEF(git2r_branch_get_upstream, 1), CALLDEF(git2r_branch_is_head, 1), CALLDEF(git2r_branch_list, 2), CALLDEF(git2r_branch_remote_name, 1), CALLDEF(git2r_branch_remote_url, 1), CALLDEF(git2r_branch_rename, 3), CALLDEF(git2r_branch_set_upstream, 2), CALLDEF(git2r_branch_target, 1), CALLDEF(git2r_branch_upstream_canonical_name, 1), CALLDEF(git2r_checkout_path, 2), CALLDEF(git2r_checkout_tree, 3), CALLDEF(git2r_clone, 7), CALLDEF(git2r_commit, 4), CALLDEF(git2r_commit_parent_list, 1), CALLDEF(git2r_commit_tree, 1), CALLDEF(git2r_config_find_file, 1), CALLDEF(git2r_config_get, 1), CALLDEF(git2r_config_get_logical, 2), CALLDEF(git2r_config_get_string, 2), CALLDEF(git2r_config_set, 2), CALLDEF(git2r_diff, 12), CALLDEF(git2r_graph_ahead_behind, 2), CALLDEF(git2r_graph_descendant_of, 2), CALLDEF(git2r_index_add_all, 3), CALLDEF(git2r_index_remove_bypath, 2), CALLDEF(git2r_libgit2_features, 0), CALLDEF(git2r_libgit2_version, 0), CALLDEF(git2r_merge_base, 2), CALLDEF(git2r_merge_branch, 4), CALLDEF(git2r_merge_fetch_heads, 2), CALLDEF(git2r_note_create, 7), CALLDEF(git2r_note_default_ref, 1), CALLDEF(git2r_notes, 2), CALLDEF(git2r_note_remove, 3), CALLDEF(git2r_object_lookup, 2), CALLDEF(git2r_odb_blobs, 1), CALLDEF(git2r_odb_hash, 1), CALLDEF(git2r_odb_hashfile, 1), CALLDEF(git2r_odb_objects, 1), CALLDEF(git2r_push, 4), CALLDEF(git2r_reference_dwim, 2), CALLDEF(git2r_reference_list, 1), CALLDEF(git2r_reflog_list, 2), CALLDEF(git2r_remote_add, 3), CALLDEF(git2r_remote_fetch, 6), CALLDEF(git2r_remote_list, 1), CALLDEF(git2r_remote_remove, 2), CALLDEF(git2r_remote_rename, 3), CALLDEF(git2r_remote_set_url, 3), CALLDEF(git2r_remote_url, 2), CALLDEF(git2r_remote_ls, 3), CALLDEF(git2r_repository_can_open, 1), CALLDEF(git2r_repository_discover, 2), CALLDEF(git2r_repository_fetch_heads, 1), CALLDEF(git2r_repository_head, 1), CALLDEF(git2r_repository_head_detached, 1), CALLDEF(git2r_repository_init, 3), CALLDEF(git2r_repository_is_bare, 1), CALLDEF(git2r_repository_is_empty, 1), CALLDEF(git2r_repository_is_shallow, 1), CALLDEF(git2r_repository_set_head, 2), CALLDEF(git2r_repository_set_head_detached, 1), CALLDEF(git2r_repository_workdir, 1), CALLDEF(git2r_reset, 2), CALLDEF(git2r_reset_default, 2), CALLDEF(git2r_revparse_single, 2), CALLDEF(git2r_revwalk_contributions, 4), CALLDEF(git2r_revwalk_list, 6), CALLDEF(git2r_revwalk_list2, 7), CALLDEF(git2r_signature_default, 1), CALLDEF(git2r_ssl_cert_locations, 2), CALLDEF(git2r_stash_apply, 2), CALLDEF(git2r_stash_drop, 2), CALLDEF(git2r_stash_list, 1), CALLDEF(git2r_stash_pop, 2), CALLDEF(git2r_stash_save, 6), CALLDEF(git2r_status_list, 6), CALLDEF(git2r_tag_create, 5), CALLDEF(git2r_tag_delete, 2), CALLDEF(git2r_tag_list, 1), CALLDEF(git2r_tree_walk, 2), {NULL, NULL, 0} }; /** * Load 'git2r' * - Register routines to R. * - Initialize libgit2 * * @param info Information about the DLL being loaded */ void attribute_visible R_init_git2r(DllInfo *info) { R_registerRoutines(info, NULL, callMethods, NULL, NULL); R_useDynamicSymbols(info, FALSE); R_forceSymbols(info, TRUE); git_libgit2_init(); } /** * Unload 'git2r' * * @param info Information about the DLL being unloaded */ void R_unload_git2r(DllInfo *info) { GIT2R_UNUSED(info); git_libgit2_shutdown(); } git2r/src/git2r_transfer.c0000644000176200001440000000416614700263364015203 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include "git2r_S3.h" #include "git2r_transfer.h" /** * Init slots in S3 class git_transfer_progress * * @param source A git_indexer_progress object * @param dest S3 class git_transfer_progress to initialize * @return void */ void attribute_hidden git2r_transfer_progress_init( const git_indexer_progress *source, SEXP dest) { SET_VECTOR_ELT( dest, git2r_S3_item__git_transfer_progress__total_objects, Rf_ScalarInteger(source->total_objects)); SET_VECTOR_ELT( dest, git2r_S3_item__git_transfer_progress__indexed_objects, Rf_ScalarInteger(source->indexed_objects)); SET_VECTOR_ELT( dest, git2r_S3_item__git_transfer_progress__received_objects, Rf_ScalarInteger(source->received_objects)); SET_VECTOR_ELT( dest, git2r_S3_item__git_transfer_progress__local_objects, Rf_ScalarInteger(source->local_objects)); SET_VECTOR_ELT( dest, git2r_S3_item__git_transfer_progress__total_deltas, Rf_ScalarInteger(source->total_deltas)); SET_VECTOR_ELT( dest, git2r_S3_item__git_transfer_progress__indexed_deltas, Rf_ScalarInteger(source->indexed_deltas)); SET_VECTOR_ELT( dest, git2r_S3_item__git_transfer_progress__received_bytes, Rf_ScalarInteger(source->received_bytes)); } git2r/src/git2r_clone.h0000644000176200001440000000177413137360640014464 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_clone_h #define INCLUDE_git2r_clone_h #include #include SEXP git2r_clone( SEXP url, SEXP local_path, SEXP bare, SEXP branch, SEXP checkout, SEXP credentials, SEXP progress); #endif git2r/src/git2r_reference.c0000644000176200001440000001315014700264711015303 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_error.h" #include "git2r_reference.h" #include "git2r_repository.h" #include "git2r_S3.h" /** * Init slots in S3 class git_reference. * * @param source A git_reference pointer * @param repo S3 class git_repository that contains the reference * @param dest S3 class git_reference to initialize * @return void */ static void git2r_reference_init( git_reference *source, SEXP repo, SEXP dest) { char sha[GIT_OID_HEXSZ + 1]; SET_VECTOR_ELT( dest, git2r_S3_item__git_reference__name, Rf_mkString(git_reference_name(source))); SET_VECTOR_ELT( dest, git2r_S3_item__git_reference__shorthand, Rf_mkString(git_reference_shorthand(source))); switch (git_reference_type(source)) { case GIT_REFERENCE_DIRECT: SET_VECTOR_ELT( dest, git2r_S3_item__git_reference__type, Rf_ScalarInteger(GIT_REFERENCE_DIRECT)); git_oid_fmt(sha, git_reference_target(source)); sha[GIT_OID_HEXSZ] = '\0'; SET_VECTOR_ELT( dest, git2r_S3_item__git_reference__sha, Rf_mkString(sha)); break; case GIT_REFERENCE_SYMBOLIC: SET_VECTOR_ELT( dest, git2r_S3_item__git_reference__type, Rf_ScalarInteger(GIT_REFERENCE_SYMBOLIC)); SET_VECTOR_ELT( dest, git2r_S3_item__git_reference__target, Rf_mkString(git_reference_symbolic_target(source))); break; default: git2r_error(__func__, NULL, git2r_err_reference, NULL); } if (Rf_isNull(VECTOR_ELT(dest, git2r_S3_item__git_reference__target))) { SET_VECTOR_ELT( dest, git2r_S3_item__git_reference__target, Rf_ScalarString(NA_STRING)); } SET_VECTOR_ELT(dest, git2r_S3_item__git_reference__repo, Rf_duplicate(repo)); } /** * Lookup the full name of a reference by DWIMing its short name * * @param repo S3 class git_repository * @param shorthand The short name for the reference * @return S3 class git_reference object */ SEXP attribute_hidden git2r_reference_dwim( SEXP repo, SEXP shorthand) { int error, nprotect = 0; SEXP result = R_NilValue; git_reference* reference = NULL; git_repository *repository = NULL; if (git2r_arg_check_string(shorthand)) git2r_error(__func__, NULL, "'shorthand'", git2r_err_string_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_reference_dwim( &reference, repository, CHAR(STRING_ELT(shorthand, 0))); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_reference)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_reference)); git2r_reference_init(reference, repo, result); cleanup: git_reference_free(reference); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Get all references that can be found in a repository. * * @param repo S3 class git_repository * @return VECXSP with S3 objects of class git_reference */ SEXP attribute_hidden git2r_reference_list( SEXP repo) { int error, nprotect = 0; size_t i; git_strarray ref_list; SEXP result = R_NilValue; SEXP names = R_NilValue; git_repository *repository = NULL; repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_reference_list(&ref_list, repository); if (error) goto cleanup; PROTECT(result = Rf_allocVector(VECSXP, ref_list.count)); nprotect++; Rf_setAttrib( result, R_NamesSymbol, names = Rf_allocVector(STRSXP, ref_list.count)); for (i = 0; i < ref_list.count; i++) { SEXP reference; git_reference *ref = NULL; error = git_reference_lookup(&ref, repository, ref_list.strings[i]); if (error) goto cleanup; SET_VECTOR_ELT( result, i, reference = Rf_mkNamed(VECSXP, git2r_S3_items__git_reference)); Rf_setAttrib(reference, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_reference)); git2r_reference_init(ref, repo, reference); SET_STRING_ELT(names, i, Rf_mkChar(ref_list.strings[i])); git_reference_free(ref); } cleanup: git_strarray_free(&ref_list); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } git2r/src/git2r_blame.c0000644000176200001440000001365314700261326014434 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_blame.h" #include "git2r_error.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_signature.h" /** * Init slots in S3 class git_blame * * Iterates over and init each git_blame_hunk * @param source a blame object * @param repo S3 class git_repository that contains the blame * @param path The path to the file to get the blame * @param dest S3 class git_blame to initialize * @return void */ void static git2r_blame_init( git_blame *source, SEXP repo, SEXP path, SEXP dest) { SEXP hunks; size_t i, n; n = git_blame_get_hunk_count(source); SET_VECTOR_ELT( dest, git2r_S3_item__git_blame__hunks, hunks = Rf_allocVector(VECSXP, n)); for (i = 0; i < n; i++) { const git_blame_hunk *hunk; hunk = git_blame_get_hunk_byindex(source, i); if (hunk) { SEXP item, signature; char sha[GIT_OID_HEXSZ + 1]; SET_VECTOR_ELT( hunks, i, item = Rf_mkNamed(VECSXP, git2r_S3_items__git_blame_hunk)); Rf_setAttrib( item, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_blame_hunk)); SET_VECTOR_ELT( item, git2r_S3_item__git_blame_hunk__lines_in_hunk, Rf_ScalarInteger(hunk->lines_in_hunk)); git_oid_fmt(sha, &(hunk->final_commit_id)); sha[GIT_OID_HEXSZ] = '\0'; SET_VECTOR_ELT( item, git2r_S3_item__git_blame_hunk__final_commit_id, Rf_mkString(sha)); SET_VECTOR_ELT( item, git2r_S3_item__git_blame_hunk__final_start_line_number, Rf_ScalarInteger(hunk->final_start_line_number)); SET_VECTOR_ELT( item, git2r_S3_item__git_blame_hunk__final_signature, signature = Rf_mkNamed(VECSXP, git2r_S3_items__git_signature)); Rf_setAttrib( signature, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_signature)); git2r_signature_init(hunk->final_signature, signature); git_oid_fmt(sha, &(hunk->orig_commit_id)); sha[GIT_OID_HEXSZ] = '\0'; SET_VECTOR_ELT( item, git2r_S3_item__git_blame_hunk__orig_commit_id, Rf_mkString(sha)); SET_VECTOR_ELT( item, git2r_S3_item__git_blame_hunk__orig_start_line_number, Rf_ScalarInteger(hunk->orig_start_line_number)); SET_VECTOR_ELT( item, git2r_S3_item__git_blame_hunk__orig_signature, signature = Rf_mkNamed(VECSXP, git2r_S3_items__git_signature)); Rf_setAttrib(signature, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_signature)); git2r_signature_init(hunk->orig_signature, signature); SET_VECTOR_ELT( item, git2r_S3_item__git_blame_hunk__orig_path, Rf_mkString(hunk->orig_path)); if (hunk->boundary) { SET_VECTOR_ELT( item, git2r_S3_item__git_blame_hunk__boundary, Rf_ScalarLogical(1)); } else { SET_VECTOR_ELT( item, git2r_S3_item__git_blame_hunk__boundary, Rf_ScalarLogical(0)); } SET_VECTOR_ELT( item, git2r_S3_item__git_blame_hunk__repo, Rf_duplicate(repo)); } } SET_VECTOR_ELT(dest, git2r_S3_item__git_blame__path, path); SET_VECTOR_ELT(dest, git2r_S3_item__git_blame__repo, Rf_duplicate(repo)); } /** * Get the blame for a single file * * @param repo S3 class git_repository that contains the blob * @param path The path to the file to get the blame * @return S3 class git_blame */ SEXP attribute_hidden git2r_blame_file( SEXP repo, SEXP path) { int error, nprotect = 0; SEXP result = R_NilValue; git_blame *blame = NULL; git_repository *repository = NULL; git_blame_options blame_opts = GIT_BLAME_OPTIONS_INIT; if (git2r_arg_check_string(path)) git2r_error(__func__, NULL, "'path'", git2r_err_string_arg); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); error = git_blame_file( &blame, repository, CHAR(STRING_ELT(path, 0)), &blame_opts); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_blame)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_blame)); git2r_blame_init(blame, repo, path, result); cleanup: git_blame_free(blame); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } git2r/src/git2r_reference.h0000644000176200001440000000171613415432334015315 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2015 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_reference_h #define INCLUDE_git2r_reference_h #include #include SEXP git2r_reference_dwim(SEXP repo, SEXP shorthand); SEXP git2r_reference_list(SEXP repo); #endif git2r/src/git2r_transfer.h0000644000176200001440000000360714700263233015202 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef INCLUDE_git2r_transfer_h #define INCLUDE_git2r_transfer_h #include #include #include /** * Data structure to hold information when performing a clone, fetch * or push operation. */ typedef struct { int received_progress; int received_done; int verbose; /* Used in the 'git2r_cred_acquire_cb' callback to determine if to * use the 'ssh-agent' to find the ssh key for authentication. * Only used when credentials equals R_NilValue. */ int use_ssh_agent; /* Used in the 'git2r_cred_acquire_cb' callback to determine if to * to search for the 'id_rsa' ssh key for authentication. Only * used when credentials equals R_NilValue. FIXME: This is * currently always set to zero, i.e. git2r does not automatically * search for the 'id_rsa' ssh key. */ int use_ssh_key; SEXP credentials; } git2r_transfer_data; #ifdef WIN32 # define GIT2R_TRANSFER_DATA_INIT {0, 0, 0, 1, 0, R_NilValue} #else # define GIT2R_TRANSFER_DATA_INIT {0, 0, 0, 1, 0, R_NilValue} #endif void git2r_transfer_progress_init( const git_indexer_progress *source, SEXP dest); #endif git2r/src/git2r_merge.c0000644000176200001440000005015014700531052014440 0ustar liggesusers/* * git2r, R bindings to the libgit2 library. * Copyright (C) 2013-2024 The git2r contributors * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, version 2, * as published by the Free Software Foundation. * * git2r is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include "git2r_arg.h" #include "git2r_commit.h" #include "git2r_error.h" #include "git2r_merge.h" #include "git2r_repository.h" #include "git2r_S3.h" #include "git2r_signature.h" int git2r_commit_create( git_oid *out, git_repository *repository, git_index *index, const char *message, git_signature *author, git_signature *committer); /** * Find a merge base between two commits * * @param one One of the commits * @param two The other commit * @return The commit of a merge base between 'one' and 'two' * or NULL if not found */ SEXP attribute_hidden git2r_merge_base( SEXP one, SEXP two) { int error, nprotect = 0; SEXP result = R_NilValue; SEXP repo_one, repo_two; SEXP sha; git_oid oid, oid_one, oid_two; git_commit *commit = NULL; git_repository *repository = NULL; if (git2r_arg_check_commit(one)) git2r_error(__func__, NULL, "'one'", git2r_err_commit_arg); if (git2r_arg_check_commit(two)) git2r_error(__func__, NULL, "'two'", git2r_err_commit_arg); repo_one = git2r_get_list_element(one, "repo"); repo_two = git2r_get_list_element(two, "repo"); if (git2r_arg_check_same_repo(repo_one, repo_two)) git2r_error(__func__, NULL, "'one' and 'two' not from same repository", NULL); repository = git2r_repository_open(repo_one); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); sha = git2r_get_list_element(one, "sha"); error = git_oid_fromstr(&oid_one, CHAR(STRING_ELT(sha, 0))); if (error) goto cleanup; sha = git2r_get_list_element(two, "sha"); error = git_oid_fromstr(&oid_two, CHAR(STRING_ELT(sha, 0))); if (error) goto cleanup; error = git_merge_base(&oid, repository, &oid_one, &oid_two); if (error) { if (GIT_ENOTFOUND == error) error = GIT_OK; goto cleanup; } error = git_commit_lookup(&commit, repository, &oid); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_commit)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_commit)); git2r_commit_init(commit, repo_one, result); cleanup: git_commit_free(commit); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Perform a fast-forward merge * * @param merge_result S3 class git_merge_result * @param merge_head The merge head to fast-forward merge * @param repository The repository * @param log_message First part of the one line long message in the reflog * @return 0 on success, or error code */ static int git2r_fast_forward_merge( SEXP merge_result, const git_annotated_commit *merge_head, git_repository *repository, const char *log_message) { int error; const git_oid *oid; char *buf = NULL; size_t buf_len; git_commit *commit = NULL; git_tree *tree = NULL; git_reference *reference = NULL; git_checkout_options opts = GIT_CHECKOUT_OPTIONS_INIT; oid = git_annotated_commit_id(merge_head); error = git_commit_lookup(&commit, repository, oid); if (error) goto cleanup; error = git_commit_tree(&tree, commit); if (error) goto cleanup; opts.checkout_strategy = GIT_CHECKOUT_SAFE; error = git_checkout_tree(repository, (git_object*)tree, &opts); if (error) goto cleanup; error = git_repository_head(&reference, repository); if (error) { if (GIT_ENOTFOUND != error) goto cleanup; } buf_len = strlen(log_message) + sizeof(": Fast-forward"); buf = malloc(buf_len); if (!buf) { giterr_set_oom(); error = GIT_ERROR_NOMEMORY; goto cleanup; } error = snprintf(buf, buf_len, "%s: Fast-forward", log_message); if (error < 0 || (size_t)error >= buf_len) { giterr_set_str(GIT_ERROR_OS, "Failed to snprintf log message."); error = GIT_ERROR_OS; goto cleanup; } if (GIT_ENOTFOUND == error) { error = git_reference_create( &reference, repository, "HEAD", git_commit_id(commit), 0, /* force */ buf); } else { git_reference *target_ref = NULL; error = git_reference_set_target( &target_ref, reference, git_commit_id(commit), buf); if (target_ref) git_reference_free(target_ref); } SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__fast_forward, Rf_ScalarLogical(1)); SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__conflicts, Rf_ScalarLogical(0)); SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__sha, Rf_ScalarString(NA_STRING)); cleanup: if (buf) free(buf); git_commit_free(commit); git_reference_free(reference); git_tree_free(tree); return error; } /** * Perform a normal merge * * @param merge_result S3 class git_merge_result * @param merge_heads The merge heads to merge * @param n The number of merge heads * @param repository The repository * @param message The commit message of the merge * @param merger Who is performing the merge * @param commit_on_success Commit merge commit, if one was created * @param merge_opts Merge options * @return 0 on success, or error code */ static int git2r_normal_merge( SEXP merge_result, const git_annotated_commit **merge_heads, size_t n, git_repository *repository, const char *message, git_signature *merger, int commit_on_success, const git_checkout_options *checkout_opts, const git_merge_options *merge_opts) { int error; git_commit *commit = NULL; git_index *index = NULL; SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__fast_forward, Rf_ScalarLogical(0)); error = git_merge( repository, merge_heads, n, merge_opts, checkout_opts); if (error) { if (error == GIT_EMERGECONFLICT) { SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__conflicts, Rf_ScalarLogical(1)); SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__sha, Rf_ScalarString(NA_STRING)); error = 0; } goto cleanup; } error = git_repository_index(&index, repository); if (error) goto cleanup; if (git_index_has_conflicts(index)) { SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__conflicts, Rf_ScalarLogical(1)); SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__sha, Rf_ScalarString(NA_STRING)); } else { SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__conflicts, Rf_ScalarLogical(0)); if (commit_on_success) { char sha[GIT_OID_HEXSZ + 1]; git_oid oid; error = git2r_commit_create( &oid, repository, index, message, merger, merger); if (error) goto cleanup; git_oid_fmt(sha, &oid); sha[GIT_OID_HEXSZ] = '\0'; SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__sha, Rf_mkString(sha)); } } cleanup: git_commit_free(commit); git_index_free(index); return error; } /** * @param merge_result S3 class git_merge_result * @repository The repository * @param merge_head The merge head to merge * @param n The number of merge heads * @param preference The merge preference option (None [0], No * Fast-Forward [1] or Only Fast-Forward [2]) * @param name The name of the merge in the reflog * @param merger Who is performing the merge * @param commit_on_success Commit merge commit, if one was created * during a normal merge * @param fail If a conflict occurs, exit immediately instead of attempting to * continue resolving conflicts. * @return 0 on success, or error code */ static int git2r_merge( SEXP merge_result, git_repository *repository, const git_annotated_commit **merge_heads, size_t n, git_merge_preference_t preference, const char *name, git_signature *merger, int commit_on_success, int fail) { int error; git_merge_analysis_t merge_analysis; git_merge_preference_t merge_preference; git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT; git_merge_options merge_opts = GIT_MERGE_OPTIONS_INIT; merge_opts.rename_threshold = 50; merge_opts.target_limit = 200; if (fail) merge_opts.flags |= GIT_MERGE_FAIL_ON_CONFLICT; checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE; error = git_merge_analysis( &merge_analysis, &merge_preference, repository, merge_heads, n); if (error) return error; if (merge_analysis & GIT_MERGE_ANALYSIS_UP_TO_DATE) { SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__up_to_date, Rf_ScalarLogical(1)); SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__fast_forward, Rf_ScalarLogical(0)); SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__conflicts, Rf_ScalarLogical(0)); SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__sha, Rf_ScalarString(NA_STRING)); return 0; } else { SET_VECTOR_ELT( merge_result, git2r_S3_item__git_merge_result__up_to_date, Rf_ScalarLogical(0)); } if (GIT_MERGE_PREFERENCE_NONE == preference) preference = merge_preference; switch (preference) { case GIT_MERGE_PREFERENCE_NONE: if (merge_analysis & GIT_MERGE_ANALYSIS_FASTFORWARD) { if (1 != n) { giterr_set_str( GIT_ERROR_NONE, "Unable to perform Fast-Forward merge " "with mith multiple merge heads."); return GIT_ERROR; } error = git2r_fast_forward_merge( merge_result, merge_heads[0], repository, name); } else if (merge_analysis & GIT_MERGE_ANALYSIS_NORMAL) { error = git2r_normal_merge( merge_result, merge_heads, n, repository, name, merger, commit_on_success, &checkout_opts, &merge_opts); } break; case GIT_MERGE_PREFERENCE_NO_FASTFORWARD: if (merge_analysis & GIT_MERGE_ANALYSIS_NORMAL) { error = git2r_normal_merge( merge_result, merge_heads, n, repository, name, merger, commit_on_success, &checkout_opts, &merge_opts); } break; case GIT_MERGE_PREFERENCE_FASTFORWARD_ONLY: if (merge_analysis & GIT_MERGE_ANALYSIS_FASTFORWARD) { if (1 != n) { giterr_set_str( GIT_ERROR_NONE, "Unable to perform Fast-Forward merge " "with mith multiple merge heads."); return GIT_ERROR; } error = git2r_fast_forward_merge( merge_result, merge_heads[0], repository, name); } else { giterr_set_str(GIT_ERROR_NONE, "Unable to perform Fast-Forward merge."); return GIT_ERROR; } break; default: giterr_set_str(GIT_ERROR_NONE, "Unknown merge option"); return GIT_ERROR; } return GIT_OK; } /** * Free each git_annotated_commit in merge_heads and free memory of * merge_heads. * * @param merge_heads The vector of git_merge_head. * @param count The number of merge heads. * @return void */ static void git2r_merge_heads_free( git_annotated_commit **merge_heads, size_t n) { if (merge_heads) { size_t i = 0; for (; i < n; i++) { if (merge_heads[i]) git_annotated_commit_free(merge_heads[i]); } free(merge_heads); } } /** * Merge branch into HEAD * * @param branch S3 class git_branch to merge into HEAD. * @param merger Who is performing the merge * @param commit_on_success Commit merge commit, if one was created * during a normal merge * @param fail If a conflict occurs, exit immediately instead of attempting to * continue resolving conflicts. * @return S3 class git_merge_result */ SEXP attribute_hidden git2r_merge_branch( SEXP branch, SEXP merger, SEXP commit_on_success, SEXP fail) { int error, nprotect = 0; SEXP result = R_NilValue; const char *name; char *buf = NULL; size_t buf_len; git_branch_t type; git_annotated_commit **merge_heads = NULL; git_reference *reference = NULL; git_repository *repository = NULL; git_signature *who = NULL; if (git2r_arg_check_branch(branch)) git2r_error(__func__, NULL, "'branch'", git2r_err_branch_arg); if (git2r_arg_check_logical(commit_on_success)) git2r_error(__func__, NULL, "'commit_on_success'", git2r_err_logical_arg); if (git2r_arg_check_signature(merger)) git2r_error(__func__, NULL, "'merger'", git2r_err_signature_arg); error = git2r_signature_from_arg(&who, merger); if (error) goto cleanup; repository = git2r_repository_open(git2r_get_list_element(branch, "repo")); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); name = CHAR(STRING_ELT(git2r_get_list_element(branch, "name"), 0)); type = INTEGER(git2r_get_list_element(branch, "type"))[0]; error = git_branch_lookup(&reference, repository, name, type); if (error) goto cleanup; merge_heads = calloc(1, sizeof(git_annotated_commit*)); if (NULL == merge_heads) { giterr_set_str(GIT_ERROR_NONE, git2r_err_alloc_memory_buffer); goto cleanup; } error = git_annotated_commit_from_ref( &(merge_heads[0]), repository, reference); if (error) goto cleanup; buf_len = strlen(name) + sizeof("merge "); buf = malloc(buf_len); if (!buf) { giterr_set_oom(); error = GIT_ERROR_NOMEMORY; goto cleanup; } error = snprintf(buf, buf_len, "merge %s", name); if (error < 0 || (size_t)error >= buf_len) { giterr_set_str(GIT_ERROR_OS, "Failed to snprintf log message."); error = GIT_ERROR_OS; goto cleanup; } PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_merge_result)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_merge_result)); error = git2r_merge( result, repository, (const git_annotated_commit **)merge_heads, 1, GIT_MERGE_PREFERENCE_NONE, buf, who, LOGICAL(commit_on_success)[0], LOGICAL(fail)[0]); cleanup: if (buf) free(buf); git_signature_free(who); git2r_merge_heads_free(merge_heads, 1); git_reference_free(reference); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } /** * Create and populate a vector of git_annotated_commit objects from * the given fetch head data. * * @param out Pointer the vector of git_annotated_commit objects. * @param repository The repository. * @param fetch_heads List of S3 class git_fetch_head objects. * @param n Length of fetch_heads list. * @return 0 on success, or error code */ static int git2r_merge_heads_from_fetch_heads( git_annotated_commit ***merge_heads, git_repository *repository, SEXP fetch_heads, size_t n) { int error = GIT_OK; size_t i; *merge_heads = calloc(n, sizeof(git_annotated_commit*)); if (!(*merge_heads)) { giterr_set_str(GIT_ERROR_NONE, git2r_err_alloc_memory_buffer); return GIT_ERROR; } for (i = 0; i < n; i++) { git_oid oid; SEXP fh = VECTOR_ELT(fetch_heads, i); error = git_oid_fromstr( &oid, CHAR(STRING_ELT(git2r_get_list_element(fh, "sha"), 0))); if (error) goto cleanup; error = git_annotated_commit_from_fetchhead( &((*merge_heads)[i]), repository, CHAR(STRING_ELT(git2r_get_list_element(fh, "ref_name"), 0)), CHAR(STRING_ELT(git2r_get_list_element(fh, "remote_url"), 0)), &oid); if (error) goto cleanup; } cleanup: if (error) { if (*merge_heads) git2r_merge_heads_free(*merge_heads, n); *merge_heads = NULL; } return error; } /** * Merge the given fetch head data into HEAD * * @param fetch_heads List of S3 class git_fetch_head objects. * @param merger Who made the merge, if the merge is non-fast forward * merge that creates a merge commit. * @return List of git_annotated_commit objects. */ SEXP attribute_hidden git2r_merge_fetch_heads( SEXP fetch_heads, SEXP merger) { int error, nprotect = 0; size_t n = 0; SEXP result = R_NilValue; git_annotated_commit **merge_heads = NULL; git_repository *repository = NULL; git_signature *who = NULL; if (git2r_arg_check_fetch_heads(fetch_heads)) git2r_error(__func__, NULL, "'fetch_heads'", git2r_err_fetch_heads_arg); if (git2r_arg_check_signature(merger)) git2r_error(__func__, NULL, "'merger'", git2r_err_signature_arg); error = git2r_signature_from_arg(&who, merger); if (error) goto cleanup; n = LENGTH(fetch_heads); if (n) { SEXP repo = git2r_get_list_element(VECTOR_ELT(fetch_heads, 0), "repo"); repository = git2r_repository_open(repo); if (!repository) git2r_error(__func__, NULL, git2r_err_invalid_repository, NULL); } error = git2r_merge_heads_from_fetch_heads( &merge_heads, repository, fetch_heads, n); if (error) goto cleanup; PROTECT(result = Rf_mkNamed(VECSXP, git2r_S3_items__git_merge_result)); nprotect++; Rf_setAttrib(result, R_ClassSymbol, Rf_mkString(git2r_S3_class__git_merge_result)); error = git2r_merge( result, repository, (const git_annotated_commit **)merge_heads, n, GIT_MERGE_PREFERENCE_NONE, "pull", who, 1, /* Commit on success */ 0); /* Don't fail on conflicts */ cleanup: git_signature_free(who); git2r_merge_heads_free(merge_heads, n); git_repository_free(repository); if (nprotect) UNPROTECT(nprotect); if (error) git2r_error(__func__, git_error_last(), NULL, NULL); return result; } git2r/NAMESPACE0000644000176200001440000001625114704743015012532 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method("[",git_tree) S3method(as.POSIXct,git_time) S3method(as.character,git_time) S3method(as.data.frame,git_commit) S3method(as.data.frame,git_repository) S3method(as.data.frame,git_tree) S3method(as.list,git_tree) S3method(diff,git_repository) S3method(diff,git_tree) S3method(format,git_blob) S3method(format,git_commit) S3method(format,git_merge_result) S3method(format,git_note) S3method(format,git_reference) S3method(format,git_signature) S3method(format,git_stash) S3method(format,git_tag) S3method(format,git_time) S3method(head,git_repository) S3method(length,git_blob) S3method(length,git_diff) S3method(length,git_tree) S3method(lookup_commit,git_branch) S3method(lookup_commit,git_commit) S3method(lookup_commit,git_reference) S3method(lookup_commit,git_tag) S3method(merge,character) S3method(merge,git_branch) S3method(merge,git_repository) S3method(plot,git_repository) S3method(print,git_blob) S3method(print,git_branch) S3method(print,git_commit) S3method(print,git_config) S3method(print,git_diff) S3method(print,git_merge_result) S3method(print,git_note) S3method(print,git_reference) S3method(print,git_reflog) S3method(print,git_reflog_entry) S3method(print,git_repository) S3method(print,git_signature) S3method(print,git_stash) S3method(print,git_status) S3method(print,git_tag) S3method(print,git_time) S3method(print,git_tree) S3method(sha,git_blob) S3method(sha,git_branch) S3method(sha,git_commit) S3method(sha,git_fetch_head) S3method(sha,git_merge_result) S3method(sha,git_note) S3method(sha,git_reference) S3method(sha,git_reflog_entry) S3method(sha,git_tag) S3method(sha,git_tree) S3method(summary,git_commit) S3method(summary,git_diff) S3method(summary,git_repository) S3method(summary,git_stash) S3method(summary,git_tag) S3method(summary,git_tree) export(add) export(ahead_behind) export(as.data.frame) export(blame) export(blob_create) export(branch_create) export(branch_delete) export(branch_get_upstream) export(branch_remote_name) export(branch_remote_url) export(branch_rename) export(branch_set_upstream) export(branch_target) export(branches) export(bundle_r_package) export(checkout) export(clone) export(commit) export(commits) export(config) export(content) export(contributions) export(cred_env) export(cred_ssh_key) export(cred_token) export(cred_user_pass) export(default_signature) export(descendant_of) export(diff) export(discover_repository) export(fetch) export(fetch_heads) export(git_config_files) export(hash) export(hashfile) export(head) export(in_repository) export(index_remove_bypath) export(init) export(is_bare) export(is_binary) export(is_blob) export(is_branch) export(is_commit) export(is_detached) export(is_empty) export(is_head) export(is_local) export(is_merge) export(is_shallow) export(is_tag) export(is_tree) export(last_commit) export(libgit2_features) export(libgit2_version) export(lookup) export(lookup_commit) export(ls_tree) export(merge) export(merge_base) export(note_create) export(note_default_ref) export(note_remove) export(notes) export(odb_blobs) export(odb_objects) export(parents) export(pull) export(punch_card) export(push) export(references) export(reflog) export(remote_add) export(remote_ls) export(remote_remove) export(remote_rename) export(remote_set_url) export(remote_url) export(remotes) export(repository) export(repository_head) export(reset) export(revparse_single) export(rm_file) export(sha) export(ssh_path) export(ssl_cert_locations) export(stash) export(stash_apply) export(stash_drop) export(stash_list) export(stash_pop) export(status) export(tag) export(tag_delete) export(tags) export(tree) export(when) export(workdir) importFrom(graphics,axis) importFrom(graphics,barplot) importFrom(graphics,par) importFrom(graphics,plot.new) importFrom(graphics,plot.window) importFrom(graphics,symbols) importFrom(graphics,title) importFrom(utils,capture.output) importFrom(utils,head) importFrom(utils,sessionInfo) useDynLib(git2r,git2r_blame_file) useDynLib(git2r,git2r_blob_content) useDynLib(git2r,git2r_blob_create_fromdisk) useDynLib(git2r,git2r_blob_create_fromworkdir) useDynLib(git2r,git2r_blob_is_binary) useDynLib(git2r,git2r_blob_rawsize) useDynLib(git2r,git2r_branch_canonical_name) useDynLib(git2r,git2r_branch_create) useDynLib(git2r,git2r_branch_delete) useDynLib(git2r,git2r_branch_get_upstream) useDynLib(git2r,git2r_branch_is_head) useDynLib(git2r,git2r_branch_list) useDynLib(git2r,git2r_branch_remote_name) useDynLib(git2r,git2r_branch_remote_url) useDynLib(git2r,git2r_branch_rename) useDynLib(git2r,git2r_branch_set_upstream) useDynLib(git2r,git2r_branch_target) useDynLib(git2r,git2r_branch_upstream_canonical_name) useDynLib(git2r,git2r_checkout_path) useDynLib(git2r,git2r_checkout_tree) useDynLib(git2r,git2r_clone) useDynLib(git2r,git2r_commit) useDynLib(git2r,git2r_commit_parent_list) useDynLib(git2r,git2r_commit_tree) useDynLib(git2r,git2r_config_find_file) useDynLib(git2r,git2r_config_get) useDynLib(git2r,git2r_config_get_string) useDynLib(git2r,git2r_config_set) useDynLib(git2r,git2r_diff) useDynLib(git2r,git2r_graph_ahead_behind) useDynLib(git2r,git2r_graph_descendant_of) useDynLib(git2r,git2r_index_add_all) useDynLib(git2r,git2r_index_remove_bypath) useDynLib(git2r,git2r_libgit2_features) useDynLib(git2r,git2r_libgit2_version) useDynLib(git2r,git2r_merge_base) useDynLib(git2r,git2r_merge_branch) useDynLib(git2r,git2r_merge_fetch_heads) useDynLib(git2r,git2r_note_create) useDynLib(git2r,git2r_note_default_ref) useDynLib(git2r,git2r_note_remove) useDynLib(git2r,git2r_notes) useDynLib(git2r,git2r_object_lookup) useDynLib(git2r,git2r_odb_blobs) useDynLib(git2r,git2r_odb_hash) useDynLib(git2r,git2r_odb_hashfile) useDynLib(git2r,git2r_odb_objects) useDynLib(git2r,git2r_push) useDynLib(git2r,git2r_reference_dwim) useDynLib(git2r,git2r_reference_list) useDynLib(git2r,git2r_reflog_list) useDynLib(git2r,git2r_remote_add) useDynLib(git2r,git2r_remote_fetch) useDynLib(git2r,git2r_remote_list) useDynLib(git2r,git2r_remote_ls) useDynLib(git2r,git2r_remote_remove) useDynLib(git2r,git2r_remote_rename) useDynLib(git2r,git2r_remote_set_url) useDynLib(git2r,git2r_remote_url) useDynLib(git2r,git2r_repository_can_open) useDynLib(git2r,git2r_repository_discover) useDynLib(git2r,git2r_repository_fetch_heads) useDynLib(git2r,git2r_repository_head) useDynLib(git2r,git2r_repository_head_detached) useDynLib(git2r,git2r_repository_init) useDynLib(git2r,git2r_repository_is_bare) useDynLib(git2r,git2r_repository_is_empty) useDynLib(git2r,git2r_repository_is_shallow) useDynLib(git2r,git2r_repository_set_head) useDynLib(git2r,git2r_repository_set_head_detached) useDynLib(git2r,git2r_repository_workdir) useDynLib(git2r,git2r_reset) useDynLib(git2r,git2r_reset_default) useDynLib(git2r,git2r_revparse_single) useDynLib(git2r,git2r_revwalk_contributions) useDynLib(git2r,git2r_revwalk_list) useDynLib(git2r,git2r_revwalk_list2) useDynLib(git2r,git2r_signature_default) useDynLib(git2r,git2r_ssl_cert_locations) useDynLib(git2r,git2r_stash_apply) useDynLib(git2r,git2r_stash_drop) useDynLib(git2r,git2r_stash_list) useDynLib(git2r,git2r_stash_pop) useDynLib(git2r,git2r_stash_save) useDynLib(git2r,git2r_status_list) useDynLib(git2r,git2r_tag_create) useDynLib(git2r,git2r_tag_delete) useDynLib(git2r,git2r_tag_list) useDynLib(git2r,git2r_tree_walk) git2r/NEWS.md0000644000176200001440000005675614705120503012417 0ustar liggesusers# git2r 0.35.0 (2024-10-20) ## CHANGES * The bundled libgit2 source code has been removed and libgit2 must now be installed on the system. * Fix build after API change in libgit2 1.8.0. * The system requirement for libgit2 has been updated to libgit2 version >= 1.0. * Add `$(C_VISIBILITY)` to compiler flags to hide internal symbols from shared object. * On MacOS, if libgit2 is not found, the build configuration tries to download a static build of libgit2 version 1.8.1 (https://github.com/autobrew/bundler/releases/tag/libgit2-1.8.1) and use that instead, after the sha256 of the downloaded 'libgit2-1.8.1-universal.tar.xz' file has been checked. # git2r 0.33.0 (2023-11-26) ## CHANGES * Added a missing 'git2r-package' alias to the documentation. * Added the argument 'raw' to the 'content' function to make it possible to get a blob content as a raw vector, see issue #461. * Updated the bundled libgit2 source code to version 1.7.1. * Changed the R dependency from >= 3.4 to >= 4.0. * Added a missing '-liconv' to PKG_LIBS in Makevars.win. # git2r 0.32.0 (2023-04-12) ## CHANGES * Updated the bundled libgit2 source code to version 1.6.3. * Fix build failure of bundled libgit2 when structure for nanosecond type is mssing. # git2r 0.31.0 (2023-01-26) ## CHANGES * Removed unused macro 'AC_PROG_CC' from the build configuration script. # git2r 0.30.1 (2022-03-15) ## CHANGES * Added the build configuration script ('src/Makevars.ucrt') for Windows UCRT. Thanks to Tomas Kalibera for providing the patch. * Added documentation about line endings in the diff function. Different operating systems handle line endings differently and to avoid problems in diffs, Git can be configured to handle these differences in line endings # git2r 0.29.0 (2021-11-18) ## CHANGES * Added a 'branch' argument to the 'init' function to make it possible to specify the branch name. * Updated the build configuration script on Windows and MacOS to use libgit2 version 1.3.0. * Updated the bundled libgit2 source code to version 1.3.0. * Renamed the NEWS file to NEWS.md and changed to use markdown format style. # git2r 0.28.0 (2021-01-10) ## IMPROVEMENTS * Updated to use libgit2 version 1.1.0 on Windows. * Fix handling of a symbolic reference when checking out previous branch. * Added a configure option '--without-libgit2' to ignore presence of a system libgit2 library and instead use the internal git2r libgit2 library. Usage: R CMD INSTALL --configure-args='--without-libgit2' git2r_x.y.z.tar.gz * Updated some tests to work with libgit2 version 1.1.0. # git2r 0.27.1 (2020-05-03) ## CHANGES * Fixed the CITATION file to pass 'R CMD check' without a NOTE. # git2r 0.27.0 (2020-05-01) ## IMPROVEMENTS * Updated the bundled libgit2 source code to version '0.28.5'. * Updated the build configuration script to be able to build git2r with a system installation of libgit2 version >= 1.0. * Updated to use libgit2 version 1.0.0 on Windows. * The build configuration script checks for minimum required version of libssh2 (version >= 1.8). Issue #420. * Updated to use roxygen2 version 7.1.0 to build the documentation. * Make it easier to view and change the timezone (John Blischak in #408). * Fixed 'ls_tree' to handle content in subfolder, see description in PR #402. * The 'branch_create' function has been changed to use the 'last_commit()' function as default to determine the commit to which the new branch should point. # git2r 0.26.1 (2019-06-30) ## BUG FIXES * Fixed the broken build on Solaris. # git2r 0.26.0 (2019-06-29) ## IMPROVEMENTS * Updated the bundled libgit2 source code to version '0.28.2'. * Added the 'force' argument to the 'tag' function to overwrite an existing tag. * Allow a zero length tag message. * Make it possible to create a lighweight tag. * Added the 'ref' argument to the 'commits' function to give a reference to list commits from. * Added the utility function 'lookup_commit' to lookup a commit related to a git object. * The 'path' argument was added to the 'commits' function to make it possible to specify that only commits modifying this file ('path') will be returned to reproduce 'git log' with '--no-follow', see the documentation. (Peter Carbonetto and John Blischak in PR #372) ## BUG FIXES * Removed the timezone offset from the commit time to fix an incorrect time in GMT when reading information from a repository (Thierry Onkelinx in PR #393). # git2r 0.25.2 (2019-03-20) ## CHANGES * Improved the build configuration script: if the system installation of libgit2 is to old, use the bundled libgit2 instead of raising an error. ## BUG FIXES * Fixed the broken build on Solaris. # git2r 0.25.1 (2019-03-17) ## BUG FIXES * Fixed significant warning from 'R CMD check' # git2r 0.25.0 (2019-03-17) ## CHANGES * Updated the bundled libgit2 source code to version '0.28.1'. * Added additional parameters to the 'diff' function to control the output, see the documentation. * Added getPass option to the password argument in 'cred_user_pass' (Annie Wang in PR #383) * Changed the 'print' functions to return its argument invisibly. * Changed the 'git_config_files' function to return a 'data.frame' * Changed the 'ahead_behind' function to accept a tag or a branch for the local and upstrean commit. * Changed the 'descendent_of' function to accept a tag or a branch for the 'commit' and 'ancestor' commit. ## BUG FIXES * Fixed memory protection errors in the git2r C source code reported by the 'rchk' tool. * Fixed listing of 'commits' from a shallow repository. * Fixed the configuration script to include the missing macro 'AM_ICONV'. # git2r 0.24.0 (2019-01-07) This is a bug-fix release. ## BUG FIXES * Fixed memory protection errors in the git2r C source code reported by the 'rchk' tool. * Raise an error if the path argument to the 'hashfile' function is NA. # git2r 0.23.0 (2018-07-17) ## IMPROVEMENTS * Updated the bundled libgit2 source code to v0.27.3 (504bd54). ## BREAKING CHANGE * On macOS, git2r no longer enables SSH transport by default. This is due to the complexity to build the dependencies for SSH transport in an R package when macOS no longer ships the OpenSSL headers. However, you can install git2r from source on macOS (see the 'R Installation and Administration' manual) with SSH transport enabled if you first install the libgit2 library, for example, using the Homebrew package manager. Another possibility is to let the build configuration automatically download the libgit2 library from the Homebrew package manager with: install.packages('git2r', type='source', configure.vars='autobrew=yes') # git2r 0.22.1 (2018-07-10) ## NEW FEATURES * Added the 'git_config_files' method to locate configuration files. * Added the 'stash_pop' method to apply a single stashed state from the stash list and remove it from the list if successful. * Added the 'stash_apply' method to apply a single stashed state from the stash list. ## IMPROVEMENTS * Updated the bundled libgit2 source code to v0.27.2 (8d36dc6). * git2r can now build against a system installation of libgit2 (Elliott Sales de Andrade in PR #345, #344 and #336). * Refactoring of the configuration scripts to use a prebuilt libgit2 on macOS and Windows (Thanks Jeroen). * Ensure that git2r writes the config file to the correct location on Windows (John Blischak in PR #320). * Better default location to find ssh keys in 'cred_ssh_key()' (Ian Lyttle in PR #317). ## BUG FIXES * If a merge results in no change, the returned 'git_merge_result' now returns 'FALSE' for 'fast_forward' and 'conflicts' and 'NA' for 'sha'. Previously it returned 'logical(0)' for 'fast_forward' and 'conflicts' and 'character(0)' for 'sha'. ## BREAKING CHANGES * Changed from S4 classes to S3 classes to simplify the design and facilitate future development. * Removed the trailing slash from the directory name when reporting repository path or workdir. * Removed the 'libgit2_sha' method. Use the 'libgit2_version' method instead. * Changed the 'stash_drop' argument 'index' from zero-based to one-based i.e. use index = 1 to drop the first stash. # git2r 0.21.0 (2018-01-04) * Added methods 'odb_blobs' and 'odb_objects' with missing repository signature. Internally, they use 'getwd' and 'discover_repository' to open a repository. ## BUG FIXES * The bundled libgit2 source code has been reverted to libgit2 v0.26.0 (15e1193) from 14 June 2017 (same as in git2r v0.19.0) to fix memory alignment errors. # git2r 0.20.0 (2017-12-17) ## IMPROVEMENTS * Updated the bundled libgit2 source code to commit (fa8cf14) from 16 December 2017. * Improvements to the build configuration script. ## BUG FIXES * Fixed the internal callback for remote host authentication from hanging indefinitely when querying an ssh-agent for credentials. Now, the callback signals an error instead of trying again if the authentication failed the first time. # git2r 0.19.0 (2017-07-19) ## IMPROVEMENTS * Updated the bundled libgit2 source code to commit (15e1193) (v0.26.0) from 14 June 2017. * Added 'checkout' argument to 'clone()'. Allows to control whether checkout of HEAD is performed after the clone is complete. Setting 'checkout=FALSE' has similar effect as the git command line option '--no-checkout'. Andrzej K. Oles in #282. ## BUG FIXES * Fixed memory protection errors in the git2r C source code reported by the 'rchk' tool. * Added missing calls to 'R_forceSymbols' and 'R_useDynamicSymbols' in the C init function. * Enable argument 'all' to commit multiple modified (or deleted) files. John Blischak in #283 * Changed the configure script to determine the architecture of the machine earlier in order to fix an unsupported architecture error encountered on CentOS (#268, #288). # git2r 0.18.0 (2017-01-01) ## BUG FIXES * This is a bug-fix release to solve an error introduced in the build configuration on mac in version 0.17.0. The package failed with 'unable to load shared object', see issue #267. # git2r 0.17.0 (2016-12-29) ## IMPROVEMENTS * Updated the bundled libgit2 source code to commit (6b0510e) from 20 December 2016. * Static linking of LibSSH2 on mac to support redistributable binary package with SSH transport enabled. Version 1.8.0 of LibSSH2 is downloaded and built from 'https://www.libssh2.org/download/'. # git2r 0.16.0 (2016-11-20) ## IMPROVEMENTS * Updated libgit2 source code to commit (6b0510e) from 17 November 2016. * Add the option 'all_untracked' to the 'status' method to show individual files in untracked directories if the 'untracked' option is TRUE. * Add the 'tag_delete' method to delete an existing tag reference. * Update build configuration to support OpenSSL 1.1.0. * If the the 'getPass' package is installed the 'cred_ssh_key' method to create a new passphrase-protected ssh key credential object will call the 'getPass::getPass()' method if the private key is passphrase protected to allow for interactive input of the passphrase. The 'getPass' package is a suggested package. (Peter Meissner in PR #254) * Add 'path' argument to the 'reset' method to enable path-specific unstage, i.e. resets the index entries for all paths to their state at HEAD ## BUG FIXES * Build configuration: use portable string equality comparison operator. This fixes the build e.g. for those without Bash as /bin/sh. (Sander Maijers in PR #243). # git2r 0.15.0 (2016-05-11) ## IMPROVEMENTS * Build configuration: 'pkg-config' is now used to find 'libssl', if possible (Elias Pipping in PR #231). * Added a method to coerce a 'git_commit' object to a 'data.frame'. * Added the method 'is_branch' to check if an object is a 'git_branch'. ## BUG FIXES * Build configuration: fixed installation with parallel make (Kirill Müller in PR #228). # git2r 0.14.0 (2016-03-13) ## IMPROVEMENTS * Updated libgit2 source code to commit (785d8c48) from 2016-03-04. This is release v0.24.0 of libgit2. * Refactoring of the build scripts. * Added a check that the configuration key is valid when setting a configuration variable and output a warning if the key is invalid. * The status method now prints "working directory clean" instead of nothing when the working directory is clean. * Added the 'refspec' argument to the 'fetch' method to specify the refs to fetch and which local refs to update. * Added a workaround to the 'commit' method to list commits in a shallow clone since the libgit2 library does not yet support this. # git2r 0.13.1 (2015-12-10) ## BUG FIXES * This is a bug-fix release to solve problems introduced in version 0.12.1: - The bundled libgit2 source code has been reverted to commit (98f7bd2) from 2015-08-05 (same as in v0.11.0) to fix memory alignment errors (clang-UBSAN and gcc-UBSAN). - OpenSSL is now used again on OS X to provide the cryptographic support for HTTPS connections to fix a significant compiler warning (arithmetic on a pointer to void is a GNU extension [-Wpointer-arith]) on r-devel-osx-x86_64-clang. - Several fixes to the build configuration on non-Windows platforms. # git2r 0.12.1 (2015-12-05) ## NEW FEATURES * Add 'remote_ls' method to list references in a remote repository akin to the `git ls-remote` command. * Add 'remote_set_url' method to set the remote's url in the configuration. * Add 'cred_token' S4 class to hold the name of the environmental variable with the secret. Default value for the name is GITHUB_PAT. * It is now possible to checkout a specific file with the 'checkout' method. * Add 'ssl_cert_locations' method to set libgit2 global option 'GIT_OPT_SET_SSL_CERT_LOCATIONS' * Add 'ceiling' argument to 'discover_repository' method to prevent search from walking up the parent directories. ## CHANGES * Improvments to the cred_* functions documentation. * Add the following default arguments to the 'cred_ssh_key' method: publickey = '~/.ssh/id_rsa.pub' and privatekey = '~/.ssh/id_rsa' * On OSX, cascade CPPFLAGS and LDFLAGS to libssh2 build to allow libssh2 to be built against a user-installed openssl, discovered by configure or from R's Makeconf. Necessary to build on OS X ≥ 10.11 * On OS X, SecureTransport is now used to provide the cryptographic support for HTTPS connections insead of OpenSSL. * The search for libssh2 during configuration (non Windows) is now done via pkg-config. * Update OpenSSL on Windows to v1.0.2d * Update libgit2 source code to commit (3f5877d) from 2015-11-12. ## BUG FIXES * Add missing credentials argument to pull method. * Fix config failure when user.name or user.email are passed as variables. * Include 'configure.ac' in the distribution. # git2r 0.11.0 (2015-08-12) ## NEW FEATURES * Add punch card plot. * Add branch argument to clone with name of the branch to checkout. * Add 'force' argument to 'add' method to add ignored files. * The following methods can now be called without the repository argument: 'branches', 'references', 'remotes', 'tags' and 'workdir'. When these methods are called without the repository argument, the repository is searched for with 'discover_repository' in the current working directory. * Add name of branch to each item in branch_list. * Add name of tag to each item in tags list. * Add S4 class 'cred_env' to pass credentials in environment variables. * SSH transport on Windows. This requires 'LibSSH2' and 'OpenSSL'. These two libraries are downloaded from 'https://github.com/rwinlib' during configuration of the package. * Static linking of LibSSH2 on OSX to support redistributable binary package with SSH transport enabled. Version 1.6.0 of LibSSH2 is downloaded and built from 'https://github.com/libssh2/libssh2'. ## IMPROVEMENTS * Better summary output from S4 classes 'git_commit' and 'git_repository'. * Updated libgit2 source code to commit (98f7bd2) from 2015-08-05. ## BUG FIXES * Add imports to DESCRIPTION to fix CRAN notes. * Fix plot function to use the repository argument 'x' * Update configuration to build on OpenBSD. * Fix checkout branch in empty repository. * Fix path argument in rm_file. * Internal refactoring of C code that raise error to prevent segfault. # git2r 0.10.1 (2015-05-07) ## CHANGES * Rename 'bundle_repo' method to 'bundle_r_package' # git2r 0.10.0 (2015-05-07) ## NEW FEATURES * Added method libgit2_sha that returns the commit id of the libgit2 library that the bundled source code is based on. * Added the method in_repository to determine if a directory is in a git repository. ## CHANGES * Add brief summary of the five latest commits when summarizing a git_respository. * Added argument 'n' to the commits method to limit the number of commits in the output. * Added the following methods with missing repository signature; commits, is_shallow, is_empty, is_detached, repository and status. Internally, these methods use getwd and discover_repository to open a repository. * Changed configuration to raise error if the OpenSSL library is not found on non-Windows systems. * Changed configuration to raise error if the iconv library is not found on OSX. * Removed print of the configuration in the config method. Changed to return S3 class git_config. * Removed print of the status in the status method. Changed to return S3 class git_status. ## BUG FIXES * Use OPENSSL_INCLUDES variable to build on Solaris. * Use bundled regex library on Solaris. git2 0.9 (2015-04-25) ## CHANGES * Single quote 'libgit2' and 'Git' in Description field git2 0.8 (2015-04-24) ## CHANGES * Added bare argument to clone method to create a bare repository * Added force argument to push to force local revision to the remote repo * Updated libgit2 source code (2a0f67f) * Internal refactoring of push ## NEW FEATURES * Added method rm_file to remove files * Added 'all' argument to commit method to stage modified and deleted files * Added shortcut to checkout previous branch with "-" which is synonymous with "@{-1}" * Added session argument to commit method to add sessionInfo to commit message * Added session argument to tag method to add sessionInfo to tag message * Added method to coerce POSIXlt to S4 class git_time * Added method 'revparse_single' to find object specified by revision * Added plot method git2 0.7 (2015-02-23) ## CHANGES * Update libgit2 source code to commit (366e53d) * Fix configuration of compiler options when the OpenSSL library is found on non-Windows platforms # git2r 0.6 (2015-02-18) ## CHANGES * Update Title and Description field in DESCRIPTION file. # git2r 0.5 (2015-02-17) ## CHANGES * Update libgit2 source code to commit (a291790) * Use Alice and Bob as placeholder names in examples. * Add COPYRIGHTS file to list all copyright holders. * Fix significant compiler warnings from R CMD check with pedantic flag. # git2r 0.4 (2015-01-13) ## CHANGES * Fix build on Windows # git2r 0.3 (2015-01-13) ## CHANGES * Internal refactoring of merge method and merge tests. * Update libgit2 source code to version v0.22.0 ## BUG FIXES * Fix build on OSX. # git2r 0.2 (2015-01-05) ## NEW FEATURES * Add method 'odb_objects' to list all objects available in the database as a data.frame * Add method 'odb_blobs' to list all blobs reachable from the commits in the object database. ## DOCUMENTATION * Added examples to all exported methods. ## CHANGES * Removed ggplot2 dependency. Moved plot functionality to the ggit package (https://github.com/ropensci/ggit). * Renamed note_list method to notes * Removed markdown_link method * Renamed diff and merge arguments ## IMPROVEMENTS * Better performance when summarizing contributions. * Improved build of package. ## BUG FIXES * Fixed memory leaks. * Fixed use of allocVector without protection. * Added unload hook to unload DLL. * Fix tree and blob tests to use writeChar instead of writeLines to have more control over line endings. # git2r 0.1 (2014-09-09) ## NEW FEATURES * Many new features and methods added, see the documention for a description of the methods below: - Blob: content, blob_create, hash, hashfile, is_binary, is_blob, length, show, summary. - Branch: branch_create, branch_delete, branch_get_upstream, branch_remote_name, branch_remote_url, branch_rename, branch_set_upstream and branch_target. - Commit: is_commit and parents. - Diff: diff and diff_print. - Fetch: fetch and fetch_heads. - Libgit2: libgit2_features and libgit2_version. - Merge: merge. - Note: note_create, note_default_ref, note_list and note_remove. - Pull: pull. - Push: push. - Remote: remote_add, remote_remove, remote_rename and remote_url. - Repository: discover_repository and is_shallow - Reset: reset. - Stash: stash, stash_drop, stash_list, show and summary. * Improved error messages to give more detailed information including which function raised the error. ## NEW S4 CLASSES * The following new S4 classes to handle the libgit2 data structures: - cred_ssh_key - cred_user_pass - git_blame - git_blame_hunk - git_blob - git_diff - git_diff_file - git_diff_hunk - git_diff_line - git_fetch_head - git_merge_result - git_note - git_reflog_entry - git_stash - git_transfer_progress - git_tree ## CHANGES * Renamed methods: - is.bare to is_bare - is.empty to is_empty - is.head to is_head - is.local to is_local * Rename hex to sha for the 40-character SHA-1 hash in method arguments and S4 class slots. # git2r 0.0.8 (2014-03-20) ## NEW FEATURES * Added method to clone repository * Added method config to set user.name and user.email in a repository * Added method status to display state of a repository # git2r 0.0.7 (2014-03-16) ## NEW FEATURES * Added method to create a commit ## CHANGES * Improved error checking # git2r 0.0.6 (2014-02-21) ## NEW FEATURES * Added method init to create a new Git repository ## CHANGES * Removed usage of testthat package when testing the package * Removed bundled zlib in src/zlib and instead link against zlib shipped with R. * Dropped usage of external pointers, S4 git_repository now keeps track of the path of the repository. # git2r 0.0.5 (2014-01-01) ## CHANGES * Renamed S4 class repository to git_repository ## NEW FEATURES * Added method commits to list all commits in repository * Added S4 class git_commit to hold infformation of a commit * Added S4 class git_time to hold time of an action * Added slot walker to S4 class git_repository # git2r 0.0.4 (2013-12-30) ## NEW FEATURES * Added method remote_url to get the url a remote in a repository * Added method workdir to get workdir of a repository * Added method remotes to list remotes of a repository * Added S4 class git_signature to hold information of an action signature (e.g. for committers, taggers, etc) ## CHANGES * Renamed S4 class tag to git_tag * Renamed S4 class branch to git_branch * Renamed S4 class reference to git_reference # git2r 0.0.3 (2013-12-29) ## NEW FEATURES * Added method branches to list branches * Added method head to retrieve head * Added method is.head to check if a branch is head * Added method is.local to check if a branch is local * Added S4 class branch to hold information of a git branch * Added method to show a reference * Added method to list all references in a repository * Added S4 class reference to hold information of a git reference # git2r 0.0.2 (2013-12-28) ## NEW FEATURES * Added is.bare method to check if a repository is bare * Added is.empty method to check if a repository is empty # git2r 0.0.1 (2013-12-28) ## NEW FEATURES * Added S4 class repository to work with a git repository * Initial package structure git2r/configure.ac0000644000176200001440000001463214704661152013603 0ustar liggesusers# git2r, R bindings to the libgit2 library. # Copyright (C) 2013-2024 The git2r contributors # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License, version 2, # as published by the Free Software Foundation. # # git2r is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. AC_PREREQ([2.69]) AC_INIT([git2r], [see.DESCRIPTION.file], [https://github.com/ropensci/git2r/issues]) AC_CONFIG_SRCDIR([src/git2r.c]) AC_CONFIG_AUX_DIR([tools]) AC_CANONICAL_HOST m4_include([tools/pkg.m4]) ## Check for brew on macOS AC_DEFUN([AC_PROG_BREW], [AC_CHECK_PROG(BREW,brew,yes)]) # Check for pkg-config PKG_PROG_PKG_CONFIG # Check for R : ${R_HOME=`R RHOME`} if test -z "${R_HOME}"; then AC_MSG_FAILURE([Could not determine R_HOME]) fi RBIN="${R_HOME}/bin/R" # Library settings m4_pattern_allow([PKG_CONFIG_NAME]) m4_pattern_allow([PKG_BREW_NAME]) PKG_CONFIG_NAME="libgit2" PKG_LIBS="-lgit2" PKG_CFLAGS="" # The minimum version of libgit2 that is compatible with git2r. LIBGIT2_MIN_VERSION=1.0 # Check if building against a custom installation of libgit2 or system # libgit2 if test "x${INCLUDE_DIR}${LIB_DIR}" = x; then if test [ -n "$PKG_CONFIG" ] ; then # Check if libgit2 is installed and have a version that is # compatible with git2r. if $PKG_CONFIG ${PKG_CONFIG_NAME} --atleast-version=${LIBGIT2_MIN_VERSION}; then PKGCONFIG_CFLAGS=`"${PKG_CONFIG}" --cflags "${PKG_CONFIG_NAME}"` PKGCONFIG_LIBS=`"${PKG_CONFIG}" --libs "${PKG_CONFIG_NAME}"` fi fi if test "x${PKGCONFIG_CFLAGS}${PKGCONFIG_LIBS}" = x; then case "${host_os}" in darwin*) AC_PROG_BREW if test "x${BREW}" = xyes; then BREWDIR=`brew --prefix` PKG_CFLAGS="-I${BREWDIR}/opt/libgit2/include" PKG_LIBS="-L${BREWDIR}/opt/libgit2/lib ${PKG_LIBS}" elif test -z "${DISABLE_AUTOBREW}"; then # Try to download a static build of libgit2 and use that. bottle_ver="1.8.1" bottle_sha256="9419deece3c3b7bec2ed8ed1caa5f4a3f3f1b049a6d17b0a75b2e05128c10fdf" bottle_url="https://github.com/autobrew/bundler/releases/download" bottle="${bottle_url}/libgit2-${bottle_ver}/libgit2-${bottle_ver}-universal.tar.xz" # Download the bottle echo "Download autobrew bundle $(basename ${bottle})" curl -sSL $bottle -o libs.tar.xz # Verify the checksum of the downloaded bottle AC_MSG_CHECKING([SHA256 checksum of downloaded $(basename ${bottle})]) : ${bottle_download_sha256=`openssl sha256 libs.tar.xz | sed -e 's:.*= ::'`} if test "x$bottle_download_sha256" != "x$bottle_sha256"; then AC_MSG_FAILURE([The SHA256 checksum of $(basename ${bottle}) didn't match]) fi AC_MSG_RESULT([yes]) # General setup BREWDIR="$PWD/.deps" mkdir -p $BREWDIR tar -xf libs.tar.xz --strip 1 -C $BREWDIR rm -f libs.tar.xz PKG_CFLAGS="-I${BREWDIR}/include" PKG_LIBS="-L${BREWDIR}/lib ${PKG_LIBS} -lssh2 -lcrypto -lcurl -lz -liconv -framework Security" # Prevent linking against other libs in /usr/local/lib for FILE in $BREWDIR/lib/*.a; do BASENAME=$(basename $FILE) LIBNAME=$(echo "${BASENAME%.*}" | cut -c4-) cp -f $FILE $BREWDIR/lib/libbrew$LIBNAME.a PKG_LIBS=$(echo $PKG_LIBS | sed "s/-l$LIBNAME /-lbrew$LIBNAME /g") done fi ;; esac else echo "Found pkg-config cflags and libs!" PKG_CFLAGS="${PKGCONFIG_CFLAGS}" PKG_LIBS="${PKGCONFIG_LIBS}" fi else echo "Found INCLUDE_DIR and/or LIB_DIR!" PKG_CFLAGS="-I${INCLUDE_DIR} ${PKG_CFLAGS}" PKG_LIBS="-L${LIB_DIR} ${PKG_LIBS}" fi # Find the compiler and compiler flags to use CC=`"${RBIN}" CMD config CC` CFLAGS=`"${RBIN}" CMD config CFLAGS` CPPFLAGS=`"${RBIN}" CMD config CPPFLAGS` # check that the version of libgit2 works with git2r. AC_MSG_CHECKING([whether the libgit2 version will work in git2r]) libgit2_ver_ok=no ${CC} ${CPPFLAGS} ${PKG_CFLAGS} ${CFLAGS} -E tools/version.c >/dev/null 2>&1 && libgit2_ver_ok=yes AC_MSG_RESULT([${libgit2_ver_ok}]) if test "x${libgit2_ver_ok}" = xno; then echo " ----------------------------------------------------------------------- Configuration failed to find libgit2 library. Try installing: * brew: libgit2 (MacOS) * deb: libgit2-dev (Debian, Ubuntu, etc) * rpm: libgit2-devel (Fedora, CentOS, RHEL) and try again. If the libgit2 library is installed on your system but the git2r configuration is unable to find it, you can specify the include and lib path to libgit2 with: given you downloaded a tar-gz archive: R CMD INSTALL git2r-.tar.gz --configure-vars='INCLUDE_DIR=/path/to/include LIB_DIR=/path/to/lib' or cloned the GitHub git2r repository into a directory: R CMD INSTALL git2r/ --configure-vars='INCLUDE_DIR=/path/to/include LIB_DIR=/path/to/lib' or download and install git2r in R using install.packages('git2r', type='source', configure.vars='LIB_DIR=-L/path/to/libs INCLUDE_DIR=-I/path/to/headers') ----------------------------------------------------------------------- " AC_MSG_FAILURE([package dependency requirement 'libgit2 >= ${LIBGIT2_MIN_VERSION}' could not be satisfied.]) fi # For debugging echo "----- Results of the git2r package configure -----" echo "" echo " PKG_CFLAGS: ${PKG_CFLAGS}" echo " PKG_LIBS: ${PKG_LIBS}" echo "" echo "--------------------------------------------------" AC_SUBST([PKG_CFLAGS], ["${PKG_CFLAGS}"]) AC_SUBST([PKG_LIBS], ["${PKG_LIBS}"]) AC_CONFIG_FILES([src/Makevars]) AC_OUTPUT git2r/inst/0000755000176200001440000000000014700551256012263 5ustar liggesusersgit2r/inst/COPYRIGHTS0000644000176200001440000000637414700545173013714 0ustar liggesusersFiles: * Comment: git2r, R bindings to the libgit2 library. Copyright: Copyright (C) 2013-2024 the git2r contributors, unless otherwise stated. See the DESCRIPTION file for details. License: GPL-2 Files: tools/install-sh Copyright: Copyright (C) 1994 X Consortium License: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Files: tools/config.sub Copyright: Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. License: GPL-2+ Files: tools/config.guess Copyright: Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. License: GPL-2+ Files: tools/missing Copyright: Copyright (C) 1996-2015 Free Software Foundation, Inc. Originally written by Fran,cois Pinard , 1996. License: GPL-2+ Files: tools/pkg.m4 Copyright: Copyright (C) 2004 Scott James Remnant . Copyright (C) 2012-2015 Dan Nicholson License: This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. As a special exception to the GNU General Public License, if you distribute this file as part of a program that contains a configuration script generated by Autoconf, you may include it under the same distribution terms that you use for the rest of that program. Use RShowDoc("GPL-2") from GNU R to display the GPL license (version 2) Use RShowDoc("LGPL-2.1") from GNU R to display the LGPL license (version 2.1) git2r/tools/0000755000176200001440000000000014705132220012435 5ustar liggesusersgit2r/tools/config.rpath0000644000176200001440000004425414530613147014763 0ustar liggesusers#! /bin/sh # Output a system dependent set of variables, describing how to set the # run time search path of shared libraries in an executable. # # Copyright 1996-2021 Free Software Foundation, Inc. # Taken from GNU libtool, 2001 # Originally by Gordon Matzigkeit , 1996 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. # # The first argument passed to this file is the canonical host specification, # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld # should be set by the caller. # # The set of defined variables is at the end of this script. # Known limitations: # - On IRIX 6.5 with CC="cc", the run time search patch must not be longer # than 256 bytes, otherwise the compiler driver will dump core. The only # known workaround is to choose shorter directory names for the build # directory and/or the installation directory. # All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a shrext=.so host="$1" host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` # Code taken from libtool.m4's _LT_CC_BASENAME. for cc_temp in $CC""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'` # Code taken from libtool.m4's _LT_COMPILER_PIC. wl= if test "$GCC" = yes; then wl='-Wl,' else case "$host_os" in aix*) wl='-Wl,' ;; mingw* | cygwin* | pw32* | os2* | cegcc*) ;; hpux9* | hpux10* | hpux11*) wl='-Wl,' ;; irix5* | irix6* | nonstopux*) wl='-Wl,' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in ecc*) wl='-Wl,' ;; icc* | ifort*) wl='-Wl,' ;; lf95*) wl='-Wl,' ;; nagfor*) wl='-Wl,-Wl,,' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) wl='-Wl,' ;; ccc*) wl='-Wl,' ;; xl* | bgxl* | bgf* | mpixl*) wl='-Wl,' ;; como) wl='-lopt=' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ F* | *Sun*Fortran*) wl= ;; *Sun\ C*) wl='-Wl,' ;; esac ;; esac ;; newsos6) ;; *nto* | *qnx*) ;; osf3* | osf4* | osf5*) wl='-Wl,' ;; rdos*) ;; solaris*) case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) wl='-Qoption ld ' ;; *) wl='-Wl,' ;; esac ;; sunos4*) wl='-Qoption ld ' ;; sysv4 | sysv4.2uw2* | sysv4.3*) wl='-Wl,' ;; sysv4*MP*) ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) wl='-Wl,' ;; unicos*) wl='-Wl,' ;; uts4*) ;; esac fi # Code taken from libtool.m4's _LT_LINKER_SHLIBS. hardcode_libdir_flag_spec= hardcode_libdir_separator= hardcode_direct=no hardcode_minus_L=no case "$host_os" in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes if test "$with_gnu_ld" = yes; then # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. # Unlike libtool, we use -rpath here, not --rpath, since the documented # option of GNU ld is called -rpath, not --rpath. hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' case "$host_os" in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no fi ;; amigaos*) case "$host_cpu" in powerpc) ;; m68k) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then : else ld_shlibs=no fi ;; haiku*) ;; interix[3-9]*) hardcode_direct=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; netbsd*) ;; solaris*) if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then ld_shlibs=no elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' else ld_shlibs=no fi ;; esac ;; sunos4*) hardcode_direct=yes ;; *) if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then : else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then hardcode_libdir_flag_spec= fi else case "$host_os" in aix3*) # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no else aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac fi hardcode_direct=yes hardcode_libdir_separator=':' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && \ strings "$collect2name" | grep resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac fi # Begin _LT_AC_SYS_LIBPATH_AIX. echo 'int main () { return 0; }' > conftest.c ${CC} ${LDFLAGS} conftest.c -o conftest aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } }'` fi if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib" fi rm -f conftest.c conftest # End _LT_AC_SYS_LIBPATH_AIX. if test "$aix_use_runtimelinking" = yes; then hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' else hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" fi fi ;; amigaos*) case "$host_cpu" in powerpc) ;; m68k) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. hardcode_libdir_flag_spec=' ' libext=lib ;; darwin* | rhapsody*) hardcode_direct=no if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then : else ld_shlibs=no fi ;; dgux*) hardcode_libdir_flag_spec='-L$libdir' ;; freebsd2.[01]*) hardcode_direct=yes hardcode_minus_L=yes ;; freebsd* | dragonfly* | midnightbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; hpux9*) hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; hpux10*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no ;; *) hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; netbsd*) hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes ;; newsos6) hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then hardcode_libdir_flag_spec='${wl}-rpath,$libdir' else case "$host_os" in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) hardcode_libdir_flag_spec='-R$libdir' ;; *) hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; osf3*) hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) if test "$GCC" = yes; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else # Both cc and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi hardcode_libdir_separator=: ;; solaris*) hardcode_libdir_flag_spec='-R$libdir' ;; sunos4*) hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes ;; sysv4) case $host_vendor in sni) hardcode_direct=yes # is this really true??? ;; siemens) hardcode_direct=no ;; motorola) hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac ;; sysv4.3*) ;; sysv4*MP*) if test -d /usr/nec; then ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) ;; sysv5* | sco3.2v5* | sco5v6*) hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' hardcode_libdir_separator=':' ;; uts4*) hardcode_libdir_flag_spec='-L$libdir' ;; *) ld_shlibs=no ;; esac fi # Check dynamic linker characteristics # Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER. # Unlike libtool.m4, here we don't care about _all_ names of the library, but # only about the one the linker finds when passed -lNAME. This is the last # element of library_names_spec in libtool.m4, or possibly two of them if the # linker has special search rules. library_names_spec= # the last element of library_names_spec in libtool.m4 libname_spec='lib$name' case "$host_os" in aix3*) library_names_spec='$libname.a' ;; aix[4-9]*) library_names_spec='$libname$shrext' ;; amigaos*) case "$host_cpu" in powerpc*) library_names_spec='$libname$shrext' ;; m68k) library_names_spec='$libname.a' ;; esac ;; beos*) library_names_spec='$libname$shrext' ;; bsdi[45]*) library_names_spec='$libname$shrext' ;; cygwin* | mingw* | pw32* | cegcc*) shrext=.dll library_names_spec='$libname.dll.a $libname.lib' ;; darwin* | rhapsody*) shrext=.dylib library_names_spec='$libname$shrext' ;; dgux*) library_names_spec='$libname$shrext' ;; freebsd[23].*) library_names_spec='$libname$shrext$versuffix' ;; freebsd* | dragonfly* | midnightbsd*) library_names_spec='$libname$shrext' ;; gnu*) library_names_spec='$libname$shrext' ;; haiku*) library_names_spec='$libname$shrext' ;; hpux9* | hpux10* | hpux11*) case $host_cpu in ia64*) shrext=.so ;; hppa*64*) shrext=.sl ;; *) shrext=.sl ;; esac library_names_spec='$libname$shrext' ;; interix[3-9]*) library_names_spec='$libname$shrext' ;; irix5* | irix6* | nonstopux*) library_names_spec='$libname$shrext' case "$host_os" in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;; *) libsuff= shlibsuff= ;; esac ;; esac ;; linux*oldld* | linux*aout* | linux*coff*) ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) library_names_spec='$libname$shrext' ;; knetbsd*-gnu) library_names_spec='$libname$shrext' ;; netbsd*) library_names_spec='$libname$shrext' ;; newsos6) library_names_spec='$libname$shrext' ;; *nto* | *qnx*) library_names_spec='$libname$shrext' ;; openbsd*) library_names_spec='$libname$shrext$versuffix' ;; os2*) libname_spec='$name' shrext=.dll library_names_spec='$libname.a' ;; osf3* | osf4* | osf5*) library_names_spec='$libname$shrext' ;; rdos*) ;; solaris*) library_names_spec='$libname$shrext' ;; sunos4*) library_names_spec='$libname$shrext$versuffix' ;; sysv4 | sysv4.3*) library_names_spec='$libname$shrext' ;; sysv4*MP*) library_names_spec='$libname$shrext' ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) library_names_spec='$libname$shrext' ;; tpf*) library_names_spec='$libname$shrext' ;; uts4*) library_names_spec='$libname$shrext' ;; esac sed_quote_subst='s/\(["`$\\]\)/\\\1/g' escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"` shlibext=`echo "$shrext" | sed -e 's,^\.,,'` escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"` LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <&2 exit 1;; esac shift;; -o) chowncmd="$chownprog $2" shift;; -s) stripcmd=$stripprog;; -t) is_target_a_directory=always dst_arg=$2 # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac shift;; -T) is_target_a_directory=never;; --version) echo "$0 $scriptversion"; exit $?;; --) shift break;; -*) echo "$0: invalid option: $1" >&2 exit 1;; *) break;; esac shift done # We allow the use of options -d and -T together, by making -d # take the precedence; this is for compatibility with GNU install. if test -n "$dir_arg"; then if test -n "$dst_arg"; then echo "$0: target directory not allowed when installing a directory." >&2 exit 1 fi fi if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then # When -d is used, all remaining arguments are directories to create. # When -t is used, the destination is already specified. # Otherwise, the last argument is the destination. Remove it from $@. for arg do if test -n "$dst_arg"; then # $@ is not empty: it contains at least $arg. set fnord "$@" "$dst_arg" shift # fnord fi shift # arg dst_arg=$arg # Protect names problematic for 'test' and other utilities. case $dst_arg in -* | [=\(\)!]) dst_arg=./$dst_arg;; esac done fi if test $# -eq 0; then if test -z "$dir_arg"; then echo "$0: no input file specified." >&2 exit 1 fi # It's OK to call 'install-sh -d' without argument. # This can happen when creating conditional directories. exit 0 fi if test -z "$dir_arg"; then if test $# -gt 1 || test "$is_target_a_directory" = always; then if test ! -d "$dst_arg"; then echo "$0: $dst_arg: Is not a directory." >&2 exit 1 fi fi fi if test -z "$dir_arg"; then do_exit='(exit $ret); exit $ret' trap "ret=129; $do_exit" 1 trap "ret=130; $do_exit" 2 trap "ret=141; $do_exit" 13 trap "ret=143; $do_exit" 15 # Set umask so as not to create temps with too-generous modes. # However, 'strip' requires both read and write access to temps. case $mode in # Optimize common cases. *644) cp_umask=133;; *755) cp_umask=22;; *[0-7]) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw='% 200' fi cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; *) if test -z "$stripcmd"; then u_plus_rw= else u_plus_rw=,u+rw fi cp_umask=$mode$u_plus_rw;; esac fi for src do # Protect names problematic for 'test' and other utilities. case $src in -* | [=\(\)!]) src=./$src;; esac if test -n "$dir_arg"; then dst=$src dstdir=$dst test -d "$dstdir" dstdir_status=$? else # Waiting for this to be detected by the "$cpprog $src $dsttmp" command # might cause directories to be created, which would be especially bad # if $src (and thus $dsttmp) contains '*'. if test ! -f "$src" && test ! -d "$src"; then echo "$0: $src does not exist." >&2 exit 1 fi if test -z "$dst_arg"; then echo "$0: no destination specified." >&2 exit 1 fi dst=$dst_arg # If destination is a directory, append the input filename; won't work # if double slashes aren't ignored. if test -d "$dst"; then if test "$is_target_a_directory" = never; then echo "$0: $dst_arg: Is a directory" >&2 exit 1 fi dstdir=$dst dst=$dstdir/`basename "$src"` dstdir_status=0 else dstdir=`dirname "$dst"` test -d "$dstdir" dstdir_status=$? fi fi obsolete_mkdir_used=false if test $dstdir_status != 0; then case $posix_mkdir in '') # Create intermediate dirs using mode 755 as modified by the umask. # This is like FreeBSD 'install' as of 1997-10-28. umask=`umask` case $stripcmd.$umask in # Optimize common cases. *[2367][2367]) mkdir_umask=$umask;; .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; *[0-7]) mkdir_umask=`expr $umask + 22 \ - $umask % 100 % 40 + $umask % 20 \ - $umask % 10 % 4 + $umask % 2 `;; *) mkdir_umask=$umask,go-w;; esac # With -d, create the new directory with the user-specified mode. # Otherwise, rely on $mkdir_umask. if test -n "$dir_arg"; then mkdir_mode=-m$mode else mkdir_mode= fi posix_mkdir=false case $umask in *[123567][0-7][0-7]) # POSIX mkdir -p sets u+wx bits regardless of umask, which # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 if (umask $mkdir_umask && exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. ls_ld_tmpdir=`ls -ld "$tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && $mkdirprog -m$different_mode -p -- "$tmpdir" && { ls_ld_tmpdir_1=`ls -ld "$tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi rmdir "$tmpdir/d" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null fi trap '' 0;; esac;; esac if $posix_mkdir && ( umask $mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" ) then : else # The umask is ridiculous, or mkdir does not conform to POSIX, # or it failed possibly due to a race condition. Create the # directory the slow way, step by step, checking for races as we go. case $dstdir in /*) prefix='/';; [-=\(\)!]*) prefix='./';; *) prefix='';; esac oIFS=$IFS IFS=/ set -f set fnord $dstdir shift set +f IFS=$oIFS prefixes= for d do test X"$d" = X && continue prefix=$prefix$d if test -d "$prefix"; then prefixes= else if $posix_mkdir; then (umask=$mkdir_umask && $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break # Don't fail if two instances are running concurrently. test -d "$prefix" || exit 1 else case $prefix in *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; *) qprefix=$prefix;; esac prefixes="$prefixes '$qprefix'" fi fi prefix=$prefix/ done if test -n "$prefixes"; then # Don't fail if two instances are running concurrently. (umask $mkdir_umask && eval "\$doit_exec \$mkdirprog $prefixes") || test -d "$dstdir" || exit 1 obsolete_mkdir_used=true fi fi fi if test -n "$dir_arg"; then { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 else # Make a couple of temp file names in the proper directory. dsttmp=$dstdir/_inst.$$_ rmtmp=$dstdir/_rm.$$_ # Trap to clean up those temp files at exit. trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 # Copy the file name to the temp name. (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && # and set any options; do chmod last to preserve setuid bits. # # If any of these fail, we abort the whole thing. If we want to # ignore errors from any of these, just make sure not to ignore # errors from the above "$doit $cpprog $src $dsttmp" command. # { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && # If -C, don't bother to copy if it wouldn't change the file. if $copy_on_change && old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && set -f && set X $old && old=:$2:$4:$5:$6 && set X $new && new=:$2:$4:$5:$6 && set +f && test "$old" = "$new" && $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 then rm -f "$dsttmp" else # Rename the file to the real destination. $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || # The rename failed, perhaps because mv can't rename something else # to itself, or perhaps because mv is so ancient that it does not # support -f. { # Now remove or move aside any old file at destination location. # We try this two ways since rm can't unlink itself on some # systems and the destination file might be busy for other # reasons. In this case, the final cleanup might fail but the new # file should still install successfully. { test ! -f "$dst" || $doit $rmcmd -f "$dst" 2>/dev/null || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } } || { echo "$0: cannot unlink or rename $dst" >&2 (exit 1); exit 1 } } && # Now rename the file to the real destination. $doit $mvcmd "$dsttmp" "$dst" } fi || exit 1 trap '' 0 fi done # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: git2r/tools/version.c0000644000176200001440000000012714700217350014271 0ustar liggesusers#include #if LIBGIT2_VER_MAJOR < 1 # error libgit2 version too old #endif git2r/tools/missing0000755000176200001440000001533113137360640014046 0ustar liggesusers#! /bin/sh # Common wrapper for a few potentially missing GNU programs. scriptversion=2016-01-11.22; # UTC # Copyright (C) 1996-2015 Free Software Foundation, Inc. # Originally written by Fran,cois Pinard , 1996. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. if test $# -eq 0; then echo 1>&2 "Try '$0 --help' for more information" exit 1 fi case $1 in --is-lightweight) # Used by our autoconf macros to check whether the available missing # script is modern enough. exit 0 ;; --run) # Back-compat with the calling convention used by older automake. shift ;; -h|--h|--he|--hel|--help) echo "\ $0 [OPTION]... PROGRAM [ARGUMENT]... Run 'PROGRAM [ARGUMENT]...', returning a proper advice when this fails due to PROGRAM being missing or too old. Options: -h, --help display this help and exit -v, --version output version information and exit Supported PROGRAM values: aclocal autoconf autoheader autom4te automake makeinfo bison yacc flex lex help2man Version suffixes to PROGRAM as well as the prefixes 'gnu-', 'gnu', and 'g' are ignored when checking the name. Send bug reports to ." exit $? ;; -v|--v|--ve|--ver|--vers|--versi|--versio|--version) echo "missing $scriptversion (GNU Automake)" exit $? ;; -*) echo 1>&2 "$0: unknown '$1' option" echo 1>&2 "Try '$0 --help' for more information" exit 1 ;; esac # Run the given program, remember its exit status. "$@"; st=$? # If it succeeded, we are done. test $st -eq 0 && exit 0 # Also exit now if we it failed (or wasn't found), and '--version' was # passed; such an option is passed most likely to detect whether the # program is present and works. case $2 in --version|--help) exit $st;; esac # Exit code 63 means version mismatch. This often happens when the user # tries to use an ancient version of a tool on a file that requires a # minimum version. if test $st -eq 63; then msg="probably too old" elif test $st -eq 127; then # Program was missing. msg="missing on your system" else # Program was found and executed, but failed. Give up. exit $st fi perl_URL=http://www.perl.org/ flex_URL=http://flex.sourceforge.net/ gnu_software_URL=http://www.gnu.org/software program_details () { case $1 in aclocal|automake) echo "The '$1' program is part of the GNU Automake package:" echo "<$gnu_software_URL/automake>" echo "It also requires GNU Autoconf, GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/autoconf>" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; autoconf|autom4te|autoheader) echo "The '$1' program is part of the GNU Autoconf package:" echo "<$gnu_software_URL/autoconf/>" echo "It also requires GNU m4 and Perl in order to run:" echo "<$gnu_software_URL/m4/>" echo "<$perl_URL>" ;; esac } give_advice () { # Normalize program name to check for. normalized_program=`echo "$1" | sed ' s/^gnu-//; t s/^gnu//; t s/^g//; t'` printf '%s\n' "'$1' is $msg." configure_deps="'configure.ac' or m4 files included by 'configure.ac'" case $normalized_program in autoconf*) echo "You should only need it if you modified 'configure.ac'," echo "or m4 files included by it." program_details 'autoconf' ;; autoheader*) echo "You should only need it if you modified 'acconfig.h' or" echo "$configure_deps." program_details 'autoheader' ;; automake*) echo "You should only need it if you modified 'Makefile.am' or" echo "$configure_deps." program_details 'automake' ;; aclocal*) echo "You should only need it if you modified 'acinclude.m4' or" echo "$configure_deps." program_details 'aclocal' ;; autom4te*) echo "You might have modified some maintainer files that require" echo "the 'autom4te' program to be rebuilt." program_details 'autom4te' ;; bison*|yacc*) echo "You should only need it if you modified a '.y' file." echo "You may want to install the GNU Bison package:" echo "<$gnu_software_URL/bison/>" ;; lex*|flex*) echo "You should only need it if you modified a '.l' file." echo "You may want to install the Fast Lexical Analyzer package:" echo "<$flex_URL>" ;; help2man*) echo "You should only need it if you modified a dependency" \ "of a man page." echo "You may want to install the GNU Help2man package:" echo "<$gnu_software_URL/help2man/>" ;; makeinfo*) echo "You should only need it if you modified a '.texi' file, or" echo "any other file indirectly affecting the aspect of the manual." echo "You might want to install the Texinfo package:" echo "<$gnu_software_URL/texinfo/>" echo "The spurious makeinfo call might also be the consequence of" echo "using a buggy 'make' (AIX, DU, IRIX), in which case you might" echo "want to install GNU make:" echo "<$gnu_software_URL/make/>" ;; *) echo "You might have modified some files without having the proper" echo "tools for further handling them. Check the 'README' file, it" echo "often tells you about the needed prerequisites for installing" echo "this package. You may also peek at any GNU archive site, in" echo "case some other package contains this missing '$1' program." ;; esac } give_advice "$1" | sed -e '1s/^/WARNING: /' \ -e '2,$s/^/ /' >&2 # Propagate the correct exit status (expected to be 127 for a program # not found, 63 for a program that failed due to version mismatch). exit $st # Local variables: # eval: (add-hook 'write-file-hooks 'time-stamp) # time-stamp-start: "scriptversion=" # time-stamp-format: "%:y-%02m-%02d.%02H" # time-stamp-time-zone: "UTC0" # time-stamp-end: "; # UTC" # End: git2r/tools/config.guess0000755000176200001440000014045014075750704014776 0ustar liggesusers#! /bin/sh # Attempt to guess a canonical system name. # Copyright 1992-2021 Free Software Foundation, Inc. timestamp='2021-01-01' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # # Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.guess # # Please send patches to . me=$(echo "$0" | sed -e 's,.*/,,') usage="\ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. Copyright 1992-2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; * ) break ;; esac done if test $# != 0; then echo "$me: too many arguments$help" >&2 exit 1 fi # CC_FOR_BUILD -- compiler used by this script. Note that the use of a # compiler to aid in system detection is discouraged as it requires # temporary files to be created and, as you can see below, it is a # headache to deal with in a portable fashion. # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still # use `HOST_CC' if defined, but it is deprecated. # Portable tmp directory creation inspired by the Autoconf team. tmp= # shellcheck disable=SC2172 trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 set_cc_for_build() { # prevent multiple calls if $tmp is already set test "$tmp" && return 0 : "${TMPDIR=/tmp}" # shellcheck disable=SC2039 { tmp=$( (umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null) && test -n "$tmp" && test -d "$tmp" ; } || { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } dummy=$tmp/dummy case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in ,,) echo "int x;" > "$dummy.c" for driver in cc gcc c89 c99 ; do if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$driver" break fi done if test x"$CC_FOR_BUILD" = x ; then CC_FOR_BUILD=no_compiler_found fi ;; ,,*) CC_FOR_BUILD=$CC ;; ,*,*) CC_FOR_BUILD=$HOST_CC ;; esac } # This is needed to find uname on a Pyramid OSx when run in the BSD universe. # (ghazi@noc.rutgers.edu 1994-08-24) if test -f /.attbin/uname ; then PATH=$PATH:/.attbin ; export PATH fi UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown case "$UNAME_SYSTEM" in Linux|GNU|GNU/*) LIBC=unknown set_cc_for_build cat <<-EOF > "$dummy.c" #include #if defined(__UCLIBC__) LIBC=uclibc #elif defined(__dietlibc__) LIBC=dietlibc #elif defined(__GLIBC__) LIBC=gnu #else #include /* First heuristic to detect musl libc. */ #ifdef __DEFINED_va_list LIBC=musl #endif #endif EOF eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')" # Second heuristic to detect musl libc. if [ "$LIBC" = unknown ] && command -v ldd >/dev/null && ldd --version 2>&1 | grep -q ^musl; then LIBC=musl fi # If the system lacks a compiler, then just pick glibc. # We could probably try harder. if [ "$LIBC" = unknown ]; then LIBC=gnu fi ;; esac # Note: order is significant - the case branches are not exclusive. case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward # compatibility and a consistent mechanism for selecting the # object file format. # # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \ "/sbin/$sysctl" 2>/dev/null || \ "/usr/sbin/$sysctl" 2>/dev/null || \ echo unknown)) case "$UNAME_MACHINE_ARCH" in aarch64eb) machine=aarch64_be-unknown ;; armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; earmv*) arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,') endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p') machine="${arch}${endian}"-unknown ;; *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently (or will in the future) and ABI. case "$UNAME_MACHINE_ARCH" in earm*) os=netbsdelf ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? os=netbsd else os=netbsdelf fi ;; *) os=netbsd ;; esac # Determine ABI tags. case "$UNAME_MACHINE_ARCH" in earm*) expr='s/^earmv[0-9]/-eabi/;s/eb$//' abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr") ;; esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) release=$(echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2) ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "$machine-${os}${release}${abi-}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//') echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//') echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//') echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" exit ;; *:MidnightBSD:*:*) echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; *:OS108:*:*) echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:Sortix:*:*) echo "$UNAME_MACHINE"-unknown-sortix exit ;; *:Twizzler:*:*) echo "$UNAME_MACHINE"-unknown-twizzler exit ;; *:Redox:*:*) echo "$UNAME_MACHINE"-unknown-redox exit ;; mips:OSF1:*.*) echo mips-dec-osf1 exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}') ;; *5.*) UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}') ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on # OSF/1 and Tru64 systems produced since 1995. I hope that # covers most systems running today. This code pipes the CPU # types through head -n 1, so we only detect the type of CPU 0. ALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1) case "$ALPHA_CPU_TYPE" in "EV4 (21064)") UNAME_MACHINE=alpha ;; "EV4.5 (21064)") UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") UNAME_MACHINE=alpha ;; "EV5 (21164)") UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo "$UNAME_MACHINE"-dec-osf"$(echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)" # Reset EXIT trap before exiting to avoid spurious non-zero exit code. exitcode=$? trap '' 0 exit $exitcode ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition exit ;; *:z/VM:*:*) echo s390-ibm-zvmoe exit ;; *:OS400:*:*) echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit ;; Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "$( (/bin/universe) 2>/dev/null)" = att ; then echo pyramid-pyramid-sysv3 else echo pyramid-pyramid-bsd fi exit ;; NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit ;; DRS?6000:unix:4.0:6*) echo sparc-icl-nx6 exit ;; DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) case $(/usr/bin/uname -p) in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')" exit ;; i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) set_cc_for_build SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then SUN_ARCH=x86_64 fi fi echo "$SUN_ARCH"-pc-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. echo sparc-sun-solaris3"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" exit ;; sun4*:SunOS:*:*) case "$(/usr/bin/arch -k)" in Series*|S4*) UNAME_RELEASE=$(uname -v) ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. echo sparc-sun-sunos"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/')" exit ;; sun3*:SunOS:*:*) echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null) test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "$(/bin/arch)" in sun3) echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not # "atarist" or "atariste" at least should have a processor # > m68000). The system name ranges from "MiNT" over "FreeMiNT" # to the lowercase version "mint" (or "freemint"). Finally # the system name "TOS" denotes a system which is actually not # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) echo m68k-milan-mint"$UNAME_RELEASE" exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) echo m68k-hades-mint"$UNAME_RELEASE" exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) echo m68k-unknown-mint"$UNAME_RELEASE" exit ;; m68k:machten:*:*) echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { #else int main (argc, argv) int argc; char *argv[]; { #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') && SYSTEM_NAME=$("$dummy" "$dummyarg") && { echo "$SYSTEM_NAME"; exit; } echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax exit ;; Motorola:*:4.3:PL8-*) echo powerpc-harris-powermax exit ;; Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) echo powerpc-harris-powermax exit ;; Night_Hawk:Power_UNIX:*:*) echo powerpc-harris-powerunix exit ;; m88k:CX/UX:7*:*) echo m88k-harris-cxux7 exit ;; m88k:*:4*:R4*) echo m88k-motorola-sysv4 exit ;; m88k:*:3*:R3*) echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) # DG/UX returns AViiON for all architectures UNAME_PROCESSOR=$(/usr/bin/uname -p) if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110 then if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \ test "$TARGET_BINARY_INTERFACE"x = x then echo m88k-dg-dgux"$UNAME_RELEASE" else echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else echo i586-dg-dgux"$UNAME_RELEASE" fi exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; M88*:*:R3*:*) # Delta 88k system running SVR3 echo m88k-motorola-sysv3 exit ;; XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) echo m88k-tektronix-sysv3 exit ;; Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) echo mips-sgi-irix"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/g')" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id exit ;; # Note that: echo "'$(uname -s)'" gives 'AIX ' i*86:AIX:*:*) echo i386-ibm-aix exit ;; ia64:AIX:*:*) if test -x /usr/bin/oslevel ; then IBM_REV=$(/usr/bin/oslevel) else IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include main() { if (!__power_pc()) exit(1); puts("powerpc-ibm-aix3.2.5"); exit(0); } EOF if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") then echo "$SYSTEM_NAME" else echo rs6000-ibm-aix3.2.5 fi elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 else echo rs6000-ibm-aix3.2 fi exit ;; *:AIX:*:[4567]) IBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }') if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi if test -x /usr/bin/lslpp ; then IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc | awk -F: '{ print $3 }' | sed s/[0-9]*$/0/) else IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx exit ;; DPX/2?00:B.O.S.:*:*) echo m68k-bull-sysv3 exit ;; 9000/[34]??:4.3bsd:1.*:*) echo m68k-hp-bsd exit ;; hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//') case "$UNAME_MACHINE" in 9000/31?) HP_ARCH=m68000 ;; 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if test -x /usr/bin/getconf; then sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null) sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null) case "$sc_cpu_version" in 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 532) # CPU_PA_RISC2_0 case "$sc_kernel_bits" in 32) HP_ARCH=hppa2.0n ;; 64) HP_ARCH=hppa2.0w ;; '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 esac ;; esac fi if test "$HP_ARCH" = ""; then set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #define _HPUX_SOURCE #include #include int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); #endif long cpu = sysconf (_SC_CPU_VERSION); switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; default: puts ("hppa2.0"); break; } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; #endif default: puts ("hppa1.0"); break; } exit (0); } EOF (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=$("$dummy") test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac if test "$HP_ARCH" = hppa2.0w then set_cc_for_build # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler # generating 64-bit code. GNU and HP use different nomenclature: # # $ CC_FOR_BUILD=cc ./config.guess # => hppa2.0w-hp-hpux11.23 # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | grep -q __LP64__ then HP_ARCH=hppa2.0w else HP_ARCH=hppa64 fi fi echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//') echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) set_cc_for_build sed 's/^ //' << EOF > "$dummy.c" #include int main () { long cpu = sysconf (_SC_CPU_VERSION); /* The order matters, because CPU_IS_HP_MC68K erroneously returns true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct results, however. */ if (CPU_IS_PA_RISC (cpu)) { switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; default: puts ("hppa-hitachi-hiuxwe2"); break; } } else if (CPU_IS_HP_MC68K (cpu)) puts ("m68k-hitachi-hiuxwe2"); else puts ("unknown-hitachi-hiuxwe2"); exit (0); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit ;; *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) echo hppa1.0-hp-osf exit ;; i*86:OSF1:*:*) if test -x /usr/sbin/sysversion ; then echo "$UNAME_MACHINE"-unknown-osf1mk else echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz) FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/') echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; 5000:UNIX_System_V:4.*:*) FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///') FUJITSU_REL=$(echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/') echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; arm:FreeBSD:*:*) UNAME_PROCESSOR=$(uname -p) set_cc_for_build if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi else echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf fi exit ;; *:FreeBSD:*:*) UNAME_PROCESSOR=$(/usr/bin/uname -p) case "$UNAME_PROCESSOR" in amd64) UNAME_PROCESSOR=x86_64 ;; i386) UNAME_PROCESSOR=i586 ;; esac echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')" exit ;; i*:CYGWIN*:*) echo "$UNAME_MACHINE"-pc-cygwin exit ;; *:MINGW64*:*) echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) echo "$UNAME_MACHINE"-pc-mingw32 exit ;; *:MSYS*:*) echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) echo "$UNAME_MACHINE"-pc-pw32 exit ;; *:Interix*:*) case "$UNAME_MACHINE" in x86) echo i586-pc-interix"$UNAME_RELEASE" exit ;; authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; i*:UWIN*:*) echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-pc-cygwin exit ;; prep*:SunOS:5.*:*) echo powerpcle-unknown-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')" exit ;; *:GNU:*:*) # the GNU system echo "$(echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,')-unknown-$LIBC$(echo "$UNAME_RELEASE"|sed -e 's,/.*$,,')" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland echo "$UNAME_MACHINE-unknown-$(echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC" exit ;; *:Minix:*:*) echo "$UNAME_MACHINE"-unknown-minix exit ;; aarch64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; aarch64_be:Linux:*:*) UNAME_MACHINE=aarch64_be echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) in EV5) UNAME_MACHINE=alphaev5 ;; EV56) UNAME_MACHINE=alphaev56 ;; PCA56) UNAME_MACHINE=alphapca56 ;; PCA57) UNAME_MACHINE=alphapca56 ;; EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; esac objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arc:Linux:*:* | arceb:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) set_cc_for_build if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_EABI__ then echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" else if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ARM_PCS_VFP then echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi else echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf fi fi exit ;; avr32*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; cris:Linux:*:*) echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; crisv32:Linux:*:*) echo "$UNAME_MACHINE"-axis-linux-"$LIBC" exit ;; e2k:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; frv:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; hexagon:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:Linux:*:*) echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; ia64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; k1om:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m32r*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; m68*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; mips:Linux:*:* | mips64:Linux:*:*) set_cc_for_build IS_GLIBC=0 test x"${LIBC}" = xgnu && IS_GLIBC=1 sed 's/^ //' << EOF > "$dummy.c" #undef CPU #undef mips #undef mipsel #undef mips64 #undef mips64el #if ${IS_GLIBC} && defined(_ABI64) LIBCABI=gnuabi64 #else #if ${IS_GLIBC} && defined(_ABIN32) LIBCABI=gnuabin32 #else LIBCABI=${LIBC} #endif #endif #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa64r6 #else #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 CPU=mipsisa32r6 #else #if defined(__mips64) CPU=mips64 #else CPU=mips #endif #endif #endif #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) MIPS_ENDIAN=el #else #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) MIPS_ENDIAN= #else MIPS_ENDIAN= #endif #endif EOF eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')" test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } ;; mips64el:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; openrisc*:Linux:*:*) echo or1k-unknown-linux-"$LIBC" exit ;; or32:Linux:*:* | or1k*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) echo sparc-unknown-linux-"$LIBC" exit ;; parisc64:Linux:*:* | hppa64:Linux:*:*) echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; ppc64:Linux:*:*) echo powerpc64-unknown-linux-"$LIBC" exit ;; ppc:Linux:*:*) echo powerpc-unknown-linux-"$LIBC" exit ;; ppc64le:Linux:*:*) echo powerpc64le-unknown-linux-"$LIBC" exit ;; ppcle:Linux:*:*) echo powerpcle-unknown-linux-"$LIBC" exit ;; riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; tile*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) set_cc_for_build LIBCABI=$LIBC if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_X32 >/dev/null then LIBCABI="$LIBC"x32 fi fi echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI" exit ;; xtensa*:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both # sysname and nodename. echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) # Unixware is an offshoot of SVR4, but it has its own version # number series starting with 2... # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. # Use sysv4.2uw... so that sysv4* matches it. echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) echo "$UNAME_MACHINE"-pc-syllable exit ;; i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; i*86:*:4.*:*) UNAME_REL=$(echo "$UNAME_RELEASE" | sed 's/\/MP$//') if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) # UnixWare 7.x, OpenUNIX and OpenServer 6. case $(/bin/uname -X | grep "^Machine") in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=$(sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=$( (/bin/uname -X|grep Release|sed -e 's/.*= //')) (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: # uname -m prints for DJGPP always 'pc', but it prints nothing about # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; paragon:*:*:*) echo i860-intel-osf1 exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) # "miniframe" echo m68010-convergent-sysv exit ;; mc68k:UNIX:SYSTEM5:3.51m) echo m68k-convergent-sysv exit ;; M680?0:D-NIX:5.3:*) echo m68k-diab-dnix exit ;; M68*:*:R3V[5678]*:*) test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) OS_REL='' test -r /etc/.relid \ && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid) /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 exit ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit ;; *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=$( (uname -p) 2>/dev/null) echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort # says echo i586-unisys-sysv4 exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm echo hppa1.1-stratus-sysv4 exit ;; *:*:*:FTX*) # From seanf@swdc.stratus.com. echo i860-stratus-sysv4 exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if test -d /usr/nec; then echo mips-nec-sysv"$UNAME_RELEASE" else echo mips-unknown-sysv"$UNAME_RELEASE" fi exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. echo powerpc-apple-beos exit ;; BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; x86_64:Haiku:*:*) echo x86_64-unknown-haiku exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) echo sx8r-nec-superux"$UNAME_RELEASE" exit ;; SX-ACE:SUPER-UX:*:*) echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; arm64:Darwin:*:*) echo aarch64-apple-darwin"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=$(uname -p) case $UNAME_PROCESSOR in unknown) UNAME_PROCESSOR=powerpc ;; esac if command -v xcode-select > /dev/null 2> /dev/null && \ ! xcode-select --print-path > /dev/null 2> /dev/null ; then # Avoid executing cc if there is no toolchain installed as # cc will be a stub that puts up a graphical alert # prompting the user to install developer tools. CC_FOR_BUILD=no_compiler_found else set_cc_for_build fi if test "$CC_FOR_BUILD" != no_compiler_found; then if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then case $UNAME_PROCESSOR in i386) UNAME_PROCESSOR=x86_64 ;; powerpc) UNAME_PROCESSOR=powerpc64 ;; esac fi # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_PPC >/dev/null then UNAME_PROCESSOR=powerpc fi elif test "$UNAME_PROCESSOR" = i386 ; then # uname -m returns i386 or x86_64 UNAME_PROCESSOR=$UNAME_MACHINE fi echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=$(uname -p) if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; NEO-*:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk"$UNAME_RELEASE" exit ;; NSR-*:NONSTOP_KERNEL:*:*) echo nsr-tandem-nsk"$UNAME_RELEASE" exit ;; NSV-*:NONSTOP_KERNEL:*:*) echo nsv-tandem-nsk"$UNAME_RELEASE" exit ;; NSX-*:NONSTOP_KERNEL:*:*) echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux exit ;; BS2000:POSIX*:*:*) echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. # shellcheck disable=SC2154 if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 exit ;; *:TENEX:*:*) echo pdp10-unknown-tenex exit ;; KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) echo pdp10-dec-tops20 exit ;; XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) echo pdp10-xkl-tops20 exit ;; *:TOPS-20:*:*) echo pdp10-unknown-tops20 exit ;; *:ITS:*:*) echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) echo "$UNAME_MACHINE"-unknown-dragonfly"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')" exit ;; *:*VMS:*:*) UNAME_MACHINE=$( (uname -p) 2>/dev/null) case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; esac ;; *:XENIX:*:SysV) echo i386-pc-xenix exit ;; i*86:skyos:*:*) echo "$UNAME_MACHINE"-pc-skyos"$(echo "$UNAME_RELEASE" | sed -e 's/ .*$//')" exit ;; i*86:rdos:*:*) echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) echo "$UNAME_MACHINE"-pc-aros exit ;; x86_64:VMkernel:*:*) echo "$UNAME_MACHINE"-unknown-esx exit ;; amd64:Isilon\ OneFS:*:*) echo x86_64-unknown-onefs exit ;; *:Unleashed:*:*) echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" exit ;; esac # No uname command or uname output not recognized. set_cc_for_build cat > "$dummy.c" < #include #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #include #if defined(_SIZE_T_) || defined(SIGLOST) #include #endif #endif #endif main () { #if defined (sony) #if defined (MIPSEB) /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, I don't know.... */ printf ("mips-sony-bsd\n"); exit (0); #else #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 "4" #else "" #endif ); exit (0); #endif #endif #if defined (NeXT) #if !defined (__ARCHITECTURE__) #define __ARCHITECTURE__ "m68k" #endif int version; version=$( (hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null); if (version < 4) printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); exit (0); #endif #if defined (MULTIMAX) || defined (n16) #if defined (UMAXV) printf ("ns32k-encore-sysv\n"); exit (0); #else #if defined (CMU) printf ("ns32k-encore-mach\n"); exit (0); #else printf ("ns32k-encore-bsd\n"); exit (0); #endif #endif #endif #if defined (__386BSD__) printf ("i386-pc-bsd\n"); exit (0); #endif #if defined (sequent) #if defined (i386) printf ("i386-sequent-dynix\n"); exit (0); #endif #if defined (ns32000) printf ("ns32k-sequent-dynix\n"); exit (0); #endif #endif #if defined (_SEQUENT_) struct utsname un; uname(&un); if (strncmp(un.version, "V2", 2) == 0) { printf ("i386-sequent-ptx2\n"); exit (0); } if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ printf ("i386-sequent-ptx1\n"); exit (0); } printf ("i386-sequent-ptx\n"); exit (0); #endif #if defined (vax) #if !defined (ultrix) #include #if defined (BSD) #if BSD == 43 printf ("vax-dec-bsd4.3\n"); exit (0); #else #if BSD == 199006 printf ("vax-dec-bsd4.3reno\n"); exit (0); #else printf ("vax-dec-bsd\n"); exit (0); #endif #endif #else printf ("vax-dec-bsd\n"); exit (0); #endif #else #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname un; uname (&un); printf ("vax-dec-ultrix%s\n", un.release); exit (0); #else printf ("vax-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) #if defined(_SIZE_T_) || defined(SIGLOST) struct utsname *un; uname (&un); printf ("mips-dec-ultrix%s\n", un.release); exit (0); #else printf ("mips-dec-ultrix\n"); exit (0); #endif #endif #endif #if defined (alliant) && defined (i860) printf ("i860-alliant-bsd\n"); exit (0); #endif exit (1); } EOF $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=$($dummy) && { echo "$SYSTEM_NAME"; exit; } # Apollos put the system type in the environment. test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } echo "$0: unable to guess system type" >&2 case "$UNAME_MACHINE:$UNAME_SYSTEM" in mips:Linux | mips64:Linux) # If we got here on MIPS GNU/Linux, output extra information. cat >&2 <&2 <&2 </dev/null || echo unknown) uname -r = $( (uname -r) 2>/dev/null || echo unknown) uname -s = $( (uname -s) 2>/dev/null || echo unknown) uname -v = $( (uname -v) 2>/dev/null || echo unknown) /usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null) /bin/uname -X = $( (/bin/uname -X) 2>/dev/null) hostinfo = $( (hostinfo) 2>/dev/null) /bin/universe = $( (/bin/universe) 2>/dev/null) /usr/bin/arch -k = $( (/usr/bin/arch -k) 2>/dev/null) /bin/arch = $( (/bin/arch) 2>/dev/null) /usr/bin/oslevel = $( (/usr/bin/oslevel) 2>/dev/null) /usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null) UNAME_MACHINE = "$UNAME_MACHINE" UNAME_RELEASE = "$UNAME_RELEASE" UNAME_SYSTEM = "$UNAME_SYSTEM" UNAME_VERSION = "$UNAME_VERSION" EOF fi exit 1 # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: git2r/tools/config.sub0000755000176200001440000010273314075750704014443 0ustar liggesusers#! /bin/sh # Configuration validation subroutine script. # Copyright 1992-2021 Free Software Foundation, Inc. timestamp='2021-01-07' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that # program. This Exception is an additional permission under section 7 # of the GNU General Public License, version 3 ("GPLv3"). # Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. # You can get the latest version of this script from: # https://git.savannah.gnu.org/cgit/config.git/plain/config.sub # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. # Each package is responsible for reporting which valid configurations # it does not support. The user should be able to distinguish # a failure to support a valid configuration from a meaningless # configuration. # The goal of this file is to map all the various variations of a given # machine specification into a single specification in the form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM # or in some cases, the newer four-part form: # CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM # It is wrong to echo any other type of specification. me=$(echo "$0" | sed -e 's,.*/,,') usage="\ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit Report bugs and patches to ." version="\ GNU config.sub ($timestamp) Copyright 1992-2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." help=" Try \`$me --help' for more information." # Parse command line while test $# -gt 0 ; do case $1 in --time-stamp | --time* | -t ) echo "$timestamp" ; exit ;; --version | -v ) echo "$version" ; exit ;; --help | --h* | -h ) echo "$usage"; exit ;; -- ) # Stop option processing shift; break ;; - ) # Use stdin as input. break ;; -* ) echo "$me: invalid option $1$help" >&2 exit 1 ;; *local*) # First pass through any local machine types. echo "$1" exit ;; * ) break ;; esac done case $# in 0) echo "$me: missing argument$help" >&2 exit 1;; 1) ;; *) echo "$me: too many arguments$help" >&2 exit 1;; esac # Split fields of configuration type # shellcheck disable=SC2162 IFS="-" read field1 field2 field3 field4 <&2 exit 1 ;; *-*-*-*) basic_machine=$field1-$field2 basic_os=$field3-$field4 ;; *-*-*) # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two # parts maybe_os=$field2-$field3 case $maybe_os in nto-qnx* | linux-* | uclinux-uclibc* \ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ | storm-chaos* | os2-emx* | rtmk-nova*) basic_machine=$field1 basic_os=$maybe_os ;; android-linux) basic_machine=$field1-unknown basic_os=linux-android ;; *) basic_machine=$field1-$field2 basic_os=$field3 ;; esac ;; *-*) # A lone config we happen to match not fitting any pattern case $field1-$field2 in decstation-3100) basic_machine=mips-dec basic_os= ;; *-*) # Second component is usually, but not always the OS case $field2 in # Prevent following clause from handling this valid os sun*os*) basic_machine=$field1 basic_os=$field2 ;; # Manufacturers dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ | unicom* | ibm* | next | hp | isi* | apollo | altos* \ | convergent* | ncr* | news | 32* | 3600* | 3100* \ | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ | ultra | tti* | harris | dolphin | highlevel | gould \ | cbm | ns | masscomp | apple | axis | knuth | cray \ | microblaze* | sim | cisco \ | oki | wec | wrs | winbond) basic_machine=$field1-$field2 basic_os= ;; *) basic_machine=$field1 basic_os=$field2 ;; esac ;; esac ;; *) # Convert single-component short-hands not valid as part of # multi-component configurations. case $field1 in 386bsd) basic_machine=i386-pc basic_os=bsd ;; a29khif) basic_machine=a29k-amd basic_os=udi ;; adobe68k) basic_machine=m68010-adobe basic_os=scout ;; alliant) basic_machine=fx80-alliant basic_os= ;; altos | altos3068) basic_machine=m68k-altos basic_os= ;; am29k) basic_machine=a29k-none basic_os=bsd ;; amdahl) basic_machine=580-amdahl basic_os=sysv ;; amiga) basic_machine=m68k-unknown basic_os= ;; amigaos | amigados) basic_machine=m68k-unknown basic_os=amigaos ;; amigaunix | amix) basic_machine=m68k-unknown basic_os=sysv4 ;; apollo68) basic_machine=m68k-apollo basic_os=sysv ;; apollo68bsd) basic_machine=m68k-apollo basic_os=bsd ;; aros) basic_machine=i386-pc basic_os=aros ;; aux) basic_machine=m68k-apple basic_os=aux ;; balance) basic_machine=ns32k-sequent basic_os=dynix ;; blackfin) basic_machine=bfin-unknown basic_os=linux ;; cegcc) basic_machine=arm-unknown basic_os=cegcc ;; convex-c1) basic_machine=c1-convex basic_os=bsd ;; convex-c2) basic_machine=c2-convex basic_os=bsd ;; convex-c32) basic_machine=c32-convex basic_os=bsd ;; convex-c34) basic_machine=c34-convex basic_os=bsd ;; convex-c38) basic_machine=c38-convex basic_os=bsd ;; cray) basic_machine=j90-cray basic_os=unicos ;; crds | unos) basic_machine=m68k-crds basic_os= ;; da30) basic_machine=m68k-da30 basic_os= ;; decstation | pmax | pmin | dec3100 | decstatn) basic_machine=mips-dec basic_os= ;; delta88) basic_machine=m88k-motorola basic_os=sysv3 ;; dicos) basic_machine=i686-pc basic_os=dicos ;; djgpp) basic_machine=i586-pc basic_os=msdosdjgpp ;; ebmon29k) basic_machine=a29k-amd basic_os=ebmon ;; es1800 | OSE68k | ose68k | ose | OSE) basic_machine=m68k-ericsson basic_os=ose ;; gmicro) basic_machine=tron-gmicro basic_os=sysv ;; go32) basic_machine=i386-pc basic_os=go32 ;; h8300hms) basic_machine=h8300-hitachi basic_os=hms ;; h8300xray) basic_machine=h8300-hitachi basic_os=xray ;; h8500hms) basic_machine=h8500-hitachi basic_os=hms ;; harris) basic_machine=m88k-harris basic_os=sysv3 ;; hp300 | hp300hpux) basic_machine=m68k-hp basic_os=hpux ;; hp300bsd) basic_machine=m68k-hp basic_os=bsd ;; hppaosf) basic_machine=hppa1.1-hp basic_os=osf ;; hppro) basic_machine=hppa1.1-hp basic_os=proelf ;; i386mach) basic_machine=i386-mach basic_os=mach ;; isi68 | isi) basic_machine=m68k-isi basic_os=sysv ;; m68knommu) basic_machine=m68k-unknown basic_os=linux ;; magnum | m3230) basic_machine=mips-mips basic_os=sysv ;; merlin) basic_machine=ns32k-utek basic_os=sysv ;; mingw64) basic_machine=x86_64-pc basic_os=mingw64 ;; mingw32) basic_machine=i686-pc basic_os=mingw32 ;; mingw32ce) basic_machine=arm-unknown basic_os=mingw32ce ;; monitor) basic_machine=m68k-rom68k basic_os=coff ;; morphos) basic_machine=powerpc-unknown basic_os=morphos ;; moxiebox) basic_machine=moxie-unknown basic_os=moxiebox ;; msdos) basic_machine=i386-pc basic_os=msdos ;; msys) basic_machine=i686-pc basic_os=msys ;; mvs) basic_machine=i370-ibm basic_os=mvs ;; nacl) basic_machine=le32-unknown basic_os=nacl ;; ncr3000) basic_machine=i486-ncr basic_os=sysv4 ;; netbsd386) basic_machine=i386-pc basic_os=netbsd ;; netwinder) basic_machine=armv4l-rebel basic_os=linux ;; news | news700 | news800 | news900) basic_machine=m68k-sony basic_os=newsos ;; news1000) basic_machine=m68030-sony basic_os=newsos ;; necv70) basic_machine=v70-nec basic_os=sysv ;; nh3000) basic_machine=m68k-harris basic_os=cxux ;; nh[45]000) basic_machine=m88k-harris basic_os=cxux ;; nindy960) basic_machine=i960-intel basic_os=nindy ;; mon960) basic_machine=i960-intel basic_os=mon960 ;; nonstopux) basic_machine=mips-compaq basic_os=nonstopux ;; os400) basic_machine=powerpc-ibm basic_os=os400 ;; OSE68000 | ose68000) basic_machine=m68000-ericsson basic_os=ose ;; os68k) basic_machine=m68k-none basic_os=os68k ;; paragon) basic_machine=i860-intel basic_os=osf ;; parisc) basic_machine=hppa-unknown basic_os=linux ;; psp) basic_machine=mipsallegrexel-sony basic_os=psp ;; pw32) basic_machine=i586-unknown basic_os=pw32 ;; rdos | rdos64) basic_machine=x86_64-pc basic_os=rdos ;; rdos32) basic_machine=i386-pc basic_os=rdos ;; rom68k) basic_machine=m68k-rom68k basic_os=coff ;; sa29200) basic_machine=a29k-amd basic_os=udi ;; sei) basic_machine=mips-sei basic_os=seiux ;; sequent) basic_machine=i386-sequent basic_os= ;; sps7) basic_machine=m68k-bull basic_os=sysv2 ;; st2000) basic_machine=m68k-tandem basic_os= ;; stratus) basic_machine=i860-stratus basic_os=sysv4 ;; sun2) basic_machine=m68000-sun basic_os= ;; sun2os3) basic_machine=m68000-sun basic_os=sunos3 ;; sun2os4) basic_machine=m68000-sun basic_os=sunos4 ;; sun3) basic_machine=m68k-sun basic_os= ;; sun3os3) basic_machine=m68k-sun basic_os=sunos3 ;; sun3os4) basic_machine=m68k-sun basic_os=sunos4 ;; sun4) basic_machine=sparc-sun basic_os= ;; sun4os3) basic_machine=sparc-sun basic_os=sunos3 ;; sun4os4) basic_machine=sparc-sun basic_os=sunos4 ;; sun4sol2) basic_machine=sparc-sun basic_os=solaris2 ;; sun386 | sun386i | roadrunner) basic_machine=i386-sun basic_os= ;; sv1) basic_machine=sv1-cray basic_os=unicos ;; symmetry) basic_machine=i386-sequent basic_os=dynix ;; t3e) basic_machine=alphaev5-cray basic_os=unicos ;; t90) basic_machine=t90-cray basic_os=unicos ;; toad1) basic_machine=pdp10-xkl basic_os=tops20 ;; tpf) basic_machine=s390x-ibm basic_os=tpf ;; udi29k) basic_machine=a29k-amd basic_os=udi ;; ultra3) basic_machine=a29k-nyu basic_os=sym1 ;; v810 | necv810) basic_machine=v810-nec basic_os=none ;; vaxv) basic_machine=vax-dec basic_os=sysv ;; vms) basic_machine=vax-dec basic_os=vms ;; vsta) basic_machine=i386-pc basic_os=vsta ;; vxworks960) basic_machine=i960-wrs basic_os=vxworks ;; vxworks68) basic_machine=m68k-wrs basic_os=vxworks ;; vxworks29k) basic_machine=a29k-wrs basic_os=vxworks ;; xbox) basic_machine=i686-pc basic_os=mingw32 ;; ymp) basic_machine=ymp-cray basic_os=unicos ;; *) basic_machine=$1 basic_os= ;; esac ;; esac # Decode 1-component or ad-hoc basic machines case $basic_machine in # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. w89k) cpu=hppa1.1 vendor=winbond ;; op50n) cpu=hppa1.1 vendor=oki ;; op60c) cpu=hppa1.1 vendor=oki ;; ibm*) cpu=i370 vendor=ibm ;; orion105) cpu=clipper vendor=highlevel ;; mac | mpw | mac-mpw) cpu=m68k vendor=apple ;; pmac | pmac-mpw) cpu=powerpc vendor=apple ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) cpu=m68000 vendor=att ;; 3b*) cpu=we32k vendor=att ;; bluegene*) cpu=powerpc vendor=ibm basic_os=cnk ;; decsystem10* | dec10*) cpu=pdp10 vendor=dec basic_os=tops10 ;; decsystem20* | dec20*) cpu=pdp10 vendor=dec basic_os=tops20 ;; delta | 3300 | motorola-3300 | motorola-delta \ | 3300-motorola | delta-motorola) cpu=m68k vendor=motorola ;; dpx2*) cpu=m68k vendor=bull basic_os=sysv3 ;; encore | umax | mmax) cpu=ns32k vendor=encore ;; elxsi) cpu=elxsi vendor=elxsi basic_os=${basic_os:-bsd} ;; fx2800) cpu=i860 vendor=alliant ;; genix) cpu=ns32k vendor=ns ;; h3050r* | hiux*) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; hp3k9[0-9][0-9] | hp9[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k2[0-9][0-9] | hp9k31[0-9]) cpu=m68000 vendor=hp ;; hp9k3[2-9][0-9]) cpu=m68k vendor=hp ;; hp9k6[0-9][0-9] | hp6[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; hp9k7[0-79][0-9] | hp7[0-79][0-9]) cpu=hppa1.1 vendor=hp ;; hp9k78[0-9] | hp78[0-9]) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) # FIXME: really hppa2.0-hp cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][13679] | hp8[0-9][13679]) cpu=hppa1.1 vendor=hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) cpu=hppa1.0 vendor=hp ;; i*86v32) cpu=$(echo "$1" | sed -e 's/86.*/86/') vendor=pc basic_os=sysv32 ;; i*86v4*) cpu=$(echo "$1" | sed -e 's/86.*/86/') vendor=pc basic_os=sysv4 ;; i*86v) cpu=$(echo "$1" | sed -e 's/86.*/86/') vendor=pc basic_os=sysv ;; i*86sol2) cpu=$(echo "$1" | sed -e 's/86.*/86/') vendor=pc basic_os=solaris2 ;; j90 | j90-cray) cpu=j90 vendor=cray basic_os=${basic_os:-unicos} ;; iris | iris4d) cpu=mips vendor=sgi case $basic_os in irix*) ;; *) basic_os=irix4 ;; esac ;; miniframe) cpu=m68000 vendor=convergent ;; *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) cpu=m68k vendor=atari basic_os=mint ;; news-3600 | risc-news) cpu=mips vendor=sony basic_os=newsos ;; next | m*-next) cpu=m68k vendor=next case $basic_os in openstep*) ;; nextstep*) ;; ns2*) basic_os=nextstep2 ;; *) basic_os=nextstep3 ;; esac ;; np1) cpu=np1 vendor=gould ;; op50n-* | op60c-*) cpu=hppa1.1 vendor=oki basic_os=proelf ;; pa-hitachi) cpu=hppa1.1 vendor=hitachi basic_os=hiuxwe2 ;; pbd) cpu=sparc vendor=tti ;; pbb) cpu=m68k vendor=tti ;; pc532) cpu=ns32k vendor=pc532 ;; pn) cpu=pn vendor=gould ;; power) cpu=power vendor=ibm ;; ps2) cpu=i386 vendor=ibm ;; rm[46]00) cpu=mips vendor=siemens ;; rtpc | rtpc-*) cpu=romp vendor=ibm ;; sde) cpu=mipsisa32 vendor=sde basic_os=${basic_os:-elf} ;; simso-wrs) cpu=sparclite vendor=wrs basic_os=vxworks ;; tower | tower-32) cpu=m68k vendor=ncr ;; vpp*|vx|vx-*) cpu=f301 vendor=fujitsu ;; w65) cpu=w65 vendor=wdc ;; w89k-*) cpu=hppa1.1 vendor=winbond basic_os=proelf ;; none) cpu=none vendor=none ;; leon|leon[3-9]) cpu=sparc vendor=$basic_machine ;; leon-*|leon[3-9]-*) cpu=sparc vendor=$(echo "$basic_machine" | sed 's/-.*//') ;; *-*) # shellcheck disable=SC2162 IFS="-" read cpu vendor <&2 exit 1 ;; esac ;; esac # Here we canonicalize certain aliases for manufacturers. case $vendor in digital*) vendor=dec ;; commodore*) vendor=cbm ;; *) ;; esac # Decode manufacturer-specific aliases for certain operating systems. if test x$basic_os != x then # First recognize some ad-hoc caes, or perhaps split kernel-os, or else just # set os. case $basic_os in gnu/linux*) kernel=linux os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|') ;; os2-emx) kernel=os2 os=$(echo $basic_os | sed -e 's|os2-emx|emx|') ;; nto-qnx*) kernel=nto os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|') ;; *-*) # shellcheck disable=SC2162 IFS="-" read kernel os <&2 exit 1 ;; esac # As a final step for OS-related things, validate the OS-kernel combination # (given a valid OS), if there is a kernel. case $kernel-$os in linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* ) ;; uclinux-uclibc* ) ;; -dietlibc* | -newlib* | -musl* | -uclibc* ) # These are just libc implementations, not actual OSes, and thus # require a kernel. echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 exit 1 ;; kfreebsd*-gnu* | kopensolaris*-gnu*) ;; nto-qnx*) ;; os2-emx) ;; *-eabi* | *-gnueabi*) ;; -*) # Blank kernel with real OS is always fine. ;; *-*) echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 exit 1 ;; esac # Here we handle the case where we know the os, and the CPU type, but not the # manufacturer. We pick the logical manufacturer. case $vendor in unknown) case $cpu-$os in *-riscix*) vendor=acorn ;; *-sunos*) vendor=sun ;; *-cnk* | *-aix*) vendor=ibm ;; *-beos*) vendor=be ;; *-hpux*) vendor=hp ;; *-mpeix*) vendor=hp ;; *-hiux*) vendor=hitachi ;; *-unos*) vendor=crds ;; *-dgux*) vendor=dg ;; *-luna*) vendor=omron ;; *-genix*) vendor=ns ;; *-clix*) vendor=intergraph ;; *-mvs* | *-opened*) vendor=ibm ;; *-os400*) vendor=ibm ;; s390-* | s390x-*) vendor=ibm ;; *-ptx*) vendor=sequent ;; *-tpf*) vendor=ibm ;; *-vxsim* | *-vxworks* | *-windiss*) vendor=wrs ;; *-aux*) vendor=apple ;; *-hms*) vendor=hitachi ;; *-mpw* | *-macos*) vendor=apple ;; *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) vendor=atari ;; *-vos*) vendor=stratus ;; esac ;; esac echo "$cpu-$vendor-${kernel:+$kernel-}$os" exit # Local variables: # eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" # End: git2r/tools/pkg.m40000644000176200001440000003057613443371164013505 0ustar liggesusers# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 11 (pkg-config-0.29.1) dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.1]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR dnl PKG_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND], dnl [DESCRIPTION], [DEFAULT]) dnl ------------------------------------------ dnl dnl Prepare a "--with-" configure option using the lowercase dnl [VARIABLE-PREFIX] name, merging the behaviour of AC_ARG_WITH and dnl PKG_CHECK_MODULES in a single macro. AC_DEFUN([PKG_WITH_MODULES], [ m4_pushdef([with_arg], m4_tolower([$1])) m4_pushdef([description], [m4_default([$5], [build with ]with_arg[ support])]) m4_pushdef([def_arg], [m4_default([$6], [auto])]) m4_pushdef([def_action_if_found], [AS_TR_SH([with_]with_arg)=yes]) m4_pushdef([def_action_if_not_found], [AS_TR_SH([with_]with_arg)=no]) m4_case(def_arg, [yes],[m4_pushdef([with_without], [--without-]with_arg)], [m4_pushdef([with_without],[--with-]with_arg)]) AC_ARG_WITH(with_arg, AS_HELP_STRING(with_without, description[ @<:@default=]def_arg[@:>@]),, [AS_TR_SH([with_]with_arg)=def_arg]) AS_CASE([$AS_TR_SH([with_]with_arg)], [yes],[PKG_CHECK_MODULES([$1],[$2],$3,$4)], [auto],[PKG_CHECK_MODULES([$1],[$2], [m4_n([def_action_if_found]) $3], [m4_n([def_action_if_not_found]) $4])]) m4_popdef([with_arg]) m4_popdef([description]) m4_popdef([def_arg]) ])dnl PKG_WITH_MODULES dnl PKG_HAVE_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [DESCRIPTION], [DEFAULT]) dnl ----------------------------------------------- dnl dnl Convenience macro to trigger AM_CONDITIONAL after PKG_WITH_MODULES dnl check._[VARIABLE-PREFIX] is exported as make variable. AC_DEFUN([PKG_HAVE_WITH_MODULES], [ PKG_WITH_MODULES([$1],[$2],,,[$3],[$4]) AM_CONDITIONAL([HAVE_][$1], [test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"]) ])dnl PKG_HAVE_WITH_MODULES dnl PKG_HAVE_DEFINE_WITH_MODULES(VARIABLE-PREFIX, MODULES, dnl [DESCRIPTION], [DEFAULT]) dnl ------------------------------------------------------ dnl dnl Convenience macro to run AM_CONDITIONAL and AC_DEFINE after dnl PKG_WITH_MODULES check. HAVE_[VARIABLE-PREFIX] is exported as make dnl and preprocessor variable. AC_DEFUN([PKG_HAVE_DEFINE_WITH_MODULES], [ PKG_HAVE_WITH_MODULES([$1],[$2],[$3],[$4]) AS_IF([test "$AS_TR_SH([with_]m4_tolower([$1]))" = "yes"], [AC_DEFINE([HAVE_][$1], 1, [Enable ]m4_tolower([$1])[ support])]) ])dnl PKG_HAVE_DEFINE_WITH_MODULES git2r/configure0000755000176200001440000030753514705132220013221 0ustar liggesusers#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.72 for git2r see.DESCRIPTION.file. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2017, 2020-2023 Free Software Foundation, # Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case e in #( e) case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as 'sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed 'exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test \${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which # is contrary to our usage. Disable this feature. alias -g '\${1+\"\$@\"}'='\"\$@\"' setopt NO_GLOB_SUBST else case e in #( e) case \`(set -o) 2>/dev/null\` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ) then : else case e in #( e) exitcode=1; echo positional parameters were not saved. ;; esac fi test x\$exitcode = x0 || exit 1 blah=\$(echo \$(echo blah)) test x\"\$blah\" = xblah || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" if (eval "$as_required") 2>/dev/null then : as_have_required=yes else case e in #( e) as_have_required=no ;; esac fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null then : else case e in #( e) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && as_run=a "$as_shell" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$as_shell as_have_required=yes if as_run=a "$as_shell" -c "$as_bourne_compatible""$as_suggested" 2>/dev/null then : break 2 fi fi done;; esac as_found=false done IFS=$as_save_IFS if $as_found then : else case e in #( e) if { test -f "$SHELL" || test -f "$SHELL.exe"; } && as_run=a "$SHELL" -c "$as_bourne_compatible""$as_required" 2>/dev/null then : CONFIG_SHELL=$SHELL as_have_required=yes fi ;; esac fi if test "x$CONFIG_SHELL" != x then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed 'exec'. printf "%s\n" "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno then : printf "%s\n" "$0: This script requires a shell more modern than all" printf "%s\n" "$0: the shells that I found on your system." if test ${ZSH_VERSION+y} ; then printf "%s\n" "$0: In particular, zsh $ZSH_VERSION has bugs and should" printf "%s\n" "$0: be upgraded to zsh 4.3.4 or later." else printf "%s\n" "$0: Please tell bug-autoconf@gnu.org and $0: https://github.com/ropensci/git2r/issues about your $0: system, including any error possibly output before this $0: message. Then install a modern shell, or manually run $0: the script under such a shell if you do have one." fi exit 1 fi ;; esac fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else case e in #( e) as_fn_append () { eval $1=\$$1\$2 } ;; esac fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else case e in #( e) as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } ;; esac fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' t clear :clear s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { printf "%s\n" "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable. # In both cases, we have to default to 'cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated # Sed expression to map a string onto a valid variable name. as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g" as_tr_sh="eval sed '$as_sed_sh'" # deprecated test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='git2r' PACKAGE_TARNAME='git2r' PACKAGE_VERSION='see.DESCRIPTION.file' PACKAGE_STRING='git2r see.DESCRIPTION.file' PACKAGE_BUGREPORT='https://github.com/ropensci/git2r/issues' PACKAGE_URL='' ac_unique_file="src/git2r.c" ac_subst_vars='LTLIBOBJS LIBOBJS PKG_LIBS PKG_CFLAGS BREW PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG host_os host_vendor host_cpu host build_os build_vendor build_cpu build target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir runstatedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking ' ac_precious_vars='build_alias host_alias target_alias PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -runstatedir | --runstatedir | --runstatedi | --runstated \ | --runstate | --runstat | --runsta | --runst | --runs \ | --run | --ru | --r) ac_prev=runstatedir ;; -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ | --run=* | --ru=* | --r=*) runstatedir=$ac_optarg ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: '$ac_useropt'" ac_useropt_orig=$ac_useropt ac_useropt=`printf "%s\n" "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: '$ac_option' Try '$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: '$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. printf "%s\n" "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && printf "%s\n" "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: '$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but 'cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF 'configure' configures git2r see.DESCRIPTION.file to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print 'checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for '--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or '..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, 'make install' will install all the files in '$ac_default_prefix/bin', '$ac_default_prefix/lib' etc. You can specify an installation prefix other than '$ac_default_prefix' using '--prefix', for instance '--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/git2r] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of git2r see.DESCRIPTION.file:";; esac cat <<\_ACEOF Some influential environment variables: PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path Use these variables to override the choices made by 'configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for configure.gnu first; this name is used for a wrapper for # Metaconfig's "Configure" on case-insensitive file systems. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else printf "%s\n" "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF git2r configure see.DESCRIPTION.file generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## ac_configure_args_raw= for ac_arg do case $ac_arg in *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append ac_configure_args_raw " '$ac_arg'" done case $ac_configure_args_raw in *$as_nl*) ac_safe_unquote= ;; *) ac_unsafe_z='|&;<>()$`\\"*?[ '' ' # This string ends in space, tab. ac_unsafe_a="$ac_unsafe_z#~" ac_safe_unquote="s/ '\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\)'/ \\1/g" ac_configure_args_raw=` printf "%s\n" "$ac_configure_args_raw" | sed "$ac_safe_unquote"`;; esac cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by git2r $as_me see.DESCRIPTION.file, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac printf "%s\n" "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`printf "%s\n" "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Sanitize IFS. IFS=" "" $as_nl" # Save into config.log some information that might help in debugging. { echo printf "%s\n" "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo printf "%s\n" "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then printf "%s\n" "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`printf "%s\n" "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac printf "%s\n" "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then printf "%s\n" "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && printf "%s\n" "$as_me: caught signal $ac_signal" printf "%s\n" "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h printf "%s\n" "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. printf "%s\n" "#define PACKAGE_NAME \"$PACKAGE_NAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_TARNAME \"$PACKAGE_TARNAME\"" >>confdefs.h printf "%s\n" "#define PACKAGE_VERSION \"$PACKAGE_VERSION\"" >>confdefs.h printf "%s\n" "#define PACKAGE_STRING \"$PACKAGE_STRING\"" >>confdefs.h printf "%s\n" "#define PACKAGE_BUGREPORT \"$PACKAGE_BUGREPORT\"" >>confdefs.h printf "%s\n" "#define PACKAGE_URL \"$PACKAGE_URL\"" >>confdefs.h # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. if test -n "$CONFIG_SITE"; then ac_site_files="$CONFIG_SITE" elif test "x$prefix" != xNONE; then ac_site_files="$prefix/share/config.site $prefix/etc/config.site" else ac_site_files="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" fi for ac_site_file in $ac_site_files do case $ac_site_file in #( */*) : ;; #( *) : ac_site_file=./$ac_site_file ;; esac if test -f "$ac_site_file" && test -r "$ac_site_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 printf "%s\n" "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See 'config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 printf "%s\n" "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 printf "%s\n" "$as_me: creating cache $cache_file" >&6;} >$cache_file fi # Auxiliary files required by this configure script. ac_aux_files="config.guess config.sub" # Locations in which to look for auxiliary files. ac_aux_dir_candidates="${srcdir}/tools" # Search for a directory containing all of the required auxiliary files, # $ac_aux_files, from the $PATH-style list $ac_aux_dir_candidates. # If we don't find one directory that contains all the files we need, # we report the set of missing files from the *first* directory in # $ac_aux_dir_candidates and give up. ac_missing_aux_files="" ac_first_candidate=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: looking for aux files: $ac_aux_files" >&5 as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in $ac_aux_dir_candidates do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac as_found=: printf "%s\n" "$as_me:${as_lineno-$LINENO}: trying $as_dir" >&5 ac_aux_dir_found=yes ac_install_sh= for ac_aux in $ac_aux_files do # As a special case, if "install-sh" is required, that requirement # can be satisfied by any of "install-sh", "install.sh", or "shtool", # and $ac_install_sh is set appropriately for whichever one is found. if test x"$ac_aux" = x"install-sh" then if test -f "${as_dir}install-sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install-sh found" >&5 ac_install_sh="${as_dir}install-sh -c" elif test -f "${as_dir}install.sh"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}install.sh found" >&5 ac_install_sh="${as_dir}install.sh -c" elif test -f "${as_dir}shtool"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}shtool found" >&5 ac_install_sh="${as_dir}shtool install -c" else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} install-sh" else break fi fi else if test -f "${as_dir}${ac_aux}"; then printf "%s\n" "$as_me:${as_lineno-$LINENO}: ${as_dir}${ac_aux} found" >&5 else ac_aux_dir_found=no if $ac_first_candidate; then ac_missing_aux_files="${ac_missing_aux_files} ${ac_aux}" else break fi fi fi done if test "$ac_aux_dir_found" = yes; then ac_aux_dir="$as_dir" break fi ac_first_candidate=false as_found=false done IFS=$as_save_IFS if $as_found then : else case e in #( e) as_fn_error $? "cannot find required auxiliary files:$ac_missing_aux_files" "$LINENO" 5 ;; esac fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. if test -f "${ac_aux_dir}config.guess"; then ac_config_guess="$SHELL ${ac_aux_dir}config.guess" fi if test -f "${ac_aux_dir}config.sub"; then ac_config_sub="$SHELL ${ac_aux_dir}config.sub" fi if test -f "$ac_aux_dir/configure"; then ac_configure="$SHELL ${ac_aux_dir}configure" fi # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&5 printf "%s\n" "$as_me: error: '$ac_var' was set to '$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' was not set in the previous run" >&5 printf "%s\n" "$as_me: error: '$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: '$ac_var' has changed since the previous run:" >&5 printf "%s\n" "$as_me: error: '$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&5 printf "%s\n" "$as_me: warning: ignoring whitespace changes in '$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: former value: '$ac_old_val'" >&5 printf "%s\n" "$as_me: former value: '$ac_old_val'" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: current value: '$ac_new_val'" >&5 printf "%s\n" "$as_me: current value: '$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`printf "%s\n" "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 printf "%s\n" "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run '${MAKE-make} distclean' and/or 'rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Make sure we can run config.sub. $SHELL "${ac_aux_dir}config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL ${ac_aux_dir}config.sub" "$LINENO" 5 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 printf %s "checking build system type... " >&6; } if test ${ac_cv_build+y} then : printf %s "(cached) " >&6 else case e in #( e) ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "${ac_aux_dir}config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "${ac_aux_dir}config.sub" $ac_build_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $ac_build_alias failed" "$LINENO" 5 ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 printf "%s\n" "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 printf %s "checking host system type... " >&6; } if test ${ac_cv_host+y} then : printf %s "(cached) " >&6 else case e in #( e) if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "${ac_aux_dir}config.sub" $host_alias` || as_fn_error $? "$SHELL ${ac_aux_dir}config.sub $host_alias failed" "$LINENO" 5 fi ;; esac fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 printf "%s\n" "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # serial 11 (pkg-config-0.29.1) ## Check for brew on macOS # Check for pkg-config if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_PKG_CONFIG+y} then : printf %s "(cached) " >&6 else case e in #( e) case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 printf "%s\n" "$PKG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_path_ac_pt_PKG_CONFIG+y} then : printf %s "(cached) " >&6 else case e in #( e) case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir$ac_word$ac_exec_ext" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 printf "%s\n" "$ac_pt_PKG_CONFIG" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 printf "%s\n" "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 printf %s "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } PKG_CONFIG="" fi fi # Check for R : ${R_HOME=`R RHOME`} if test -z "${R_HOME}"; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "Could not determine R_HOME See 'config.log' for more details" "$LINENO" 5; } fi RBIN="${R_HOME}/bin/R" # Library settings PKG_CONFIG_NAME="libgit2" PKG_LIBS="-lgit2" PKG_CFLAGS="" # The minimum version of libgit2 that is compatible with git2r. LIBGIT2_MIN_VERSION=1.0 # Check if building against a custom installation of libgit2 or system # libgit2 if test "x${INCLUDE_DIR}${LIB_DIR}" = x; then if test -n "$PKG_CONFIG" ; then # Check if libgit2 is installed and have a version that is # compatible with git2r. if $PKG_CONFIG ${PKG_CONFIG_NAME} --atleast-version=${LIBGIT2_MIN_VERSION}; then PKGCONFIG_CFLAGS=`"${PKG_CONFIG}" --cflags "${PKG_CONFIG_NAME}"` PKGCONFIG_LIBS=`"${PKG_CONFIG}" --libs "${PKG_CONFIG_NAME}"` fi fi if test "x${PKGCONFIG_CFLAGS}${PKGCONFIG_LIBS}" = x; then case "${host_os}" in darwin*) # Extract the first word of "brew", so it can be a program name with args. set dummy brew; ac_word=$2 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 printf %s "checking for $ac_word... " >&6; } if test ${ac_cv_prog_BREW+y} then : printf %s "(cached) " >&6 else case e in #( e) if test -n "$BREW"; then ac_cv_prog_BREW="$BREW" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir$ac_word$ac_exec_ext"; then ac_cv_prog_BREW="yes" printf "%s\n" "$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi ;; esac fi BREW=$ac_cv_prog_BREW if test -n "$BREW"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $BREW" >&5 printf "%s\n" "$BREW" >&6; } else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 printf "%s\n" "no" >&6; } fi if test "x${BREW}" = xyes; then BREWDIR=`brew --prefix` PKG_CFLAGS="-I${BREWDIR}/opt/libgit2/include" PKG_LIBS="-L${BREWDIR}/opt/libgit2/lib ${PKG_LIBS}" elif test -z "${DISABLE_AUTOBREW}"; then # Try to download a static build of libgit2 and use that. bottle_ver="1.8.1" bottle_sha256="9419deece3c3b7bec2ed8ed1caa5f4a3f3f1b049a6d17b0a75b2e05128c10fdf" bottle_url="https://github.com/autobrew/bundler/releases/download" bottle="${bottle_url}/libgit2-${bottle_ver}/libgit2-${bottle_ver}-universal.tar.xz" # Download the bottle echo "Download autobrew bundle $(basename ${bottle})" curl -sSL $bottle -o libs.tar.xz # Verify the checksum of the downloaded bottle { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking SHA256 checksum of downloaded $(basename ${bottle})" >&5 printf %s "checking SHA256 checksum of downloaded $(basename ${bottle})... " >&6; } : ${bottle_download_sha256=`openssl sha256 libs.tar.xz | sed -e 's:.*= ::'`} if test "x$bottle_download_sha256" != "x$bottle_sha256"; then { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "The SHA256 checksum of $(basename ${bottle}) didn't match See 'config.log' for more details" "$LINENO" 5; } fi { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 printf "%s\n" "yes" >&6; } # General setup BREWDIR="$PWD/.deps" mkdir -p $BREWDIR tar -xf libs.tar.xz --strip 1 -C $BREWDIR rm -f libs.tar.xz PKG_CFLAGS="-I${BREWDIR}/include" PKG_LIBS="-L${BREWDIR}/lib ${PKG_LIBS} -lssh2 -lcrypto -lcurl -lz -liconv -framework Security" # Prevent linking against other libs in /usr/local/lib for FILE in $BREWDIR/lib/*.a; do BASENAME=$(basename $FILE) LIBNAME=$(echo "${BASENAME%.*}" | cut -c4-) cp -f $FILE $BREWDIR/lib/libbrew$LIBNAME.a PKG_LIBS=$(echo $PKG_LIBS | sed "s/-l$LIBNAME /-lbrew$LIBNAME /g") done fi ;; esac else echo "Found pkg-config cflags and libs!" PKG_CFLAGS="${PKGCONFIG_CFLAGS}" PKG_LIBS="${PKGCONFIG_LIBS}" fi else echo "Found INCLUDE_DIR and/or LIB_DIR!" PKG_CFLAGS="-I${INCLUDE_DIR} ${PKG_CFLAGS}" PKG_LIBS="-L${LIB_DIR} ${PKG_LIBS}" fi # Find the compiler and compiler flags to use CC=`"${RBIN}" CMD config CC` CFLAGS=`"${RBIN}" CMD config CFLAGS` CPPFLAGS=`"${RBIN}" CMD config CPPFLAGS` # check that the version of libgit2 works with git2r. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether the libgit2 version will work in git2r" >&5 printf %s "checking whether the libgit2 version will work in git2r... " >&6; } libgit2_ver_ok=no ${CC} ${CPPFLAGS} ${PKG_CFLAGS} ${CFLAGS} -E tools/version.c >/dev/null 2>&1 && libgit2_ver_ok=yes { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ${libgit2_ver_ok}" >&5 printf "%s\n" "${libgit2_ver_ok}" >&6; } if test "x${libgit2_ver_ok}" = xno; then echo " ----------------------------------------------------------------------- Configuration failed to find libgit2 library. Try installing: * brew: libgit2 (MacOS) * deb: libgit2-dev (Debian, Ubuntu, etc) * rpm: libgit2-devel (Fedora, CentOS, RHEL) and try again. If the libgit2 library is installed on your system but the git2r configuration is unable to find it, you can specify the include and lib path to libgit2 with: given you downloaded a tar-gz archive: R CMD INSTALL git2r-.tar.gz --configure-vars='INCLUDE_DIR=/path/to/include LIB_DIR=/path/to/lib' or cloned the GitHub git2r repository into a directory: R CMD INSTALL git2r/ --configure-vars='INCLUDE_DIR=/path/to/include LIB_DIR=/path/to/lib' or download and install git2r in R using install.packages('git2r', type='source', configure.vars='LIB_DIR=-L/path/to/libs INCLUDE_DIR=-I/path/to/headers') ----------------------------------------------------------------------- " { { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5 printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;} as_fn_error $? "package dependency requirement 'libgit2 >= ${LIBGIT2_MIN_VERSION}' could not be satisfied. See 'config.log' for more details" "$LINENO" 5; } fi # For debugging echo "----- Results of the git2r package configure -----" echo "" echo " PKG_CFLAGS: ${PKG_CFLAGS}" echo " PKG_LIBS: ${PKG_LIBS}" echo "" echo "--------------------------------------------------" PKG_CFLAGS="${PKG_CFLAGS}" PKG_LIBS="${PKG_LIBS}" ac_config_files="$ac_config_files src/Makevars" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # 'ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* 'ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 printf "%s\n" "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # 'set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # 'set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test ${\1+y} || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 printf "%s\n" "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 printf "%s\n" "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' # Transform confdefs.h into DEFS. # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. # # If the first sed substitution is executed (which looks for macros that # take arguments), then branch to the quote section. Otherwise, # look for a macro that doesn't take arguments. ac_script=' :mline /\\$/{ N s,\\\n,, b mline } t clear :clear s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g t quote s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g t quote b any :quote s/[][ `~#$^&*(){}\\|;'\''"<>?]/\\&/g s/\$/$$/g H :any ${ g s/^\n// s/\n/ /g p } ' DEFS=`sed -n "$ac_script" confdefs.h` ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`printf "%s\n" "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 printf "%s\n" "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1 then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which # is contrary to our usage. Disable this feature. alias -g '${1+"$@"}'='"$@"' setopt NO_GLOB_SUBST else case e in #( e) case `(set -o) 2>/dev/null` in #( *posix*) : set -o posix ;; #( *) : ;; esac ;; esac fi # Reset variables that may have inherited troublesome values from # the environment. # IFS needs to be set, to space, tab, and newline, in precisely that order. # (If _AS_PATH_WALK were called with IFS unset, it would have the # side effect of setting IFS to empty, thus disabling word splitting.) # Quoting is to prevent editors from complaining about space-tab. as_nl=' ' export as_nl IFS=" "" $as_nl" PS1='$ ' PS2='> ' PS4='+ ' # Ensure predictable behavior from utilities with locale-dependent output. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # We cannot yet rely on "unset" to work, but we need these variables # to be unset--not just set to an empty or harmless value--now, to # avoid bugs in old shells (e.g. pre-3.0 UWIN ksh). This construct # also avoids known problems related to "unset" and subshell syntax # in other old shells (e.g. bash 2.01 and pdksh 5.2.14). for as_var in BASH_ENV ENV MAIL MAILPATH CDPATH do eval test \${$as_var+y} \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done # Ensure that fds 0, 1, and 2 are open. if (exec 3>&0) 2>/dev/null; then :; else exec 0&1) 2>/dev/null; then :; else exec 1>/dev/null; fi if (exec 3>&2) ; then :; else exec 2>/dev/null; fi # The user is always right. if ${PATH_SEPARATOR+false} :; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS case $as_dir in #((( '') as_dir=./ ;; */) ;; *) as_dir=$as_dir/ ;; esac test -r "$as_dir$0" && as_myself=$as_dir$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as 'sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then printf "%s\n" "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi printf "%s\n" "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null then : eval 'as_fn_append () { eval $1+=\$2 }' else case e in #( e) as_fn_append () { eval $1=\$$1\$2 } ;; esac fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null then : eval 'as_fn_arith () { as_val=$(( $* )) }' else case e in #( e) as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } ;; esac fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits # Determine whether it's possible to make 'echo' print without a newline. # These variables are no longer used directly by Autoconf, but are AC_SUBSTed # for compatibility with existing Makefiles. ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac # For backward compatibility with old third-party macros, we provide # the shell variables $as_echo and $as_echo_n. New code should use # AS_ECHO(["message"]) and AS_ECHO_N(["message"]), respectively. as_echo='printf %s\n' as_echo_n='printf %s' rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both 'ln -s file dir' and 'ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; 'ln -s' creates a wrapper executable. # In both cases, we have to default to 'cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`printf "%s\n" "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_sed_cpp="y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" as_tr_cpp="eval sed '$as_sed_cpp'" # deprecated # Sed expression to map a string onto a valid variable name. as_sed_sh="y%*+%pp%;s%[^_$as_cr_alnum]%_%g" as_tr_sh="eval sed '$as_sed_sh'" # deprecated exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by git2r $as_me see.DESCRIPTION.file, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ '$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE Configuration files: $config_files Report bugs to ." _ACEOF ac_cs_config=`printf "%s\n" "$ac_configure_args" | sed "$ac_safe_unquote"` ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\''/g"` cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ git2r config.status see.DESCRIPTION.file configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\" Copyright (C) 2023 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) printf "%s\n" "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) printf "%s\n" "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`printf "%s\n" "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --he | --h | --help | --hel | -h ) printf "%s\n" "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: '$1' Try '$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \printf "%s\n" "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX printf "%s\n" "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "src/Makevars") CONFIG_FILES="$CONFIG_FILES src/Makevars" ;; *) as_fn_error $? "invalid argument: '$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to '$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with './config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" eval set X " :F $CONFIG_FILES " shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag '$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain ':'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: '$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`printf "%s\n" "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is 'configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` printf "%s\n" "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { printf "%s\n" "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 printf "%s\n" "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`printf "%s\n" "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || printf "%s\n" X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`printf "%s\n" "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`printf "%s\n" "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 printf "%s\n" "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when '$srcdir' = '.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable 'datarootdir' which seems to be undefined. Please make sure it is defined" >&5 printf "%s\n" "$as_me: WARNING: $ac_file contains a reference to the variable 'datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 printf "%s\n" "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi git2r/man/0000755000176200001440000000000014704742556012072 5ustar liggesusersgit2r/man/fetch_heads.Rd0000644000176200001440000000254114704742555014617 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/fetch.R \name{fetch_heads} \alias{fetch_heads} \title{Get updated heads during the last fetch.} \usage{ fetch_heads(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ list with \code{git_fetch_head} entries. NULL if there is no FETCH_HEAD file. } \description{ Get updated heads during the last fetch. } \examples{ \dontrun{ ## Initialize three temporary repositories path_bare <- tempfile(pattern="git2r-") path_repo_1 <- tempfile(pattern="git2r-") path_repo_2 <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo_1) dir.create(path_repo_2) bare_repo <- init(path_bare, bare = TRUE) repo_1 <- clone(path_bare, path_repo_1) repo_2 <- clone(path_bare, path_repo_2) config(repo_1, user.name = "Alice", user.email = "alice@example.org") config(repo_2, user.name = "Bob", user.email = "bob@example.org") ## Add changes to repo 1 writeLines("Lorem ipsum dolor sit amet", con = file.path(path_repo_1, "example.txt")) add(repo_1, "example.txt") commit(repo_1, "Commit message") ## Push changes from repo 1 to origin (bare_repo) push(repo_1, "origin", "refs/heads/master") ## Fetch changes from origin (bare_repo) to repo 2 fetch(repo_2, "origin") ## List updated heads fetch_heads(repo_2) } } git2r/man/is_head.Rd0000644000176200001440000000174214704742555013760 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/branch.R \name{is_head} \alias{is_head} \title{Check if branch is head} \usage{ is_head(branch = NULL) } \arguments{ \item{branch}{The branch \code{object} to check if it's head.} } \value{ \code{TRUE} if branch is head, else \code{FALSE}. } \description{ Check if branch is head } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## List branches branches(repo) ## Check that 'master' is_head master <- branches(repo)[[1]] is_head(master) ## Create and checkout 'dev' branch checkout(repo, "dev", create = TRUE) ## List branches branches(repo) ## Check that 'master' is no longer head is_head(master) } } git2r/man/is_shallow.Rd0000644000176200001440000000337514704742556014535 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{is_shallow} \alias{is_shallow} \title{Determine if the repository is a shallow clone} \usage{ is_shallow(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ \code{TRUE} if shallow clone, else \code{FALSE} } \description{ Determine if the repository is a shallow clone } \examples{ \dontrun{ ## Initialize repository path_repo_1 <- tempfile(pattern="git2r-") path_repo_2 <- tempfile(pattern="git2r-") dir.create(path_repo_1) dir.create(path_repo_2) repo_1 <- init(path_repo_1) ## Config user and commit a file config(repo_1, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path_repo_1, "example.txt")) add(repo_1, "example.txt") commit(repo_1, "First commit message") ## Change file and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path_repo_1, "example.txt")) add(repo_1, "example.txt") commit(repo_1, "Second commit message") ## Change file again and commit. lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", "minim veniam, quis nostrud exercitation ullamco laboris nisi ut") writeLines(lines, file.path(path_repo_1, "example.txt")) add(repo_1, "example.txt") commit(repo_1, "Third commit message") ## Clone to second repository repo_2 <- clone(path_repo_1, path_repo_2) ## Check if it's a shallow clone is_shallow(repo_2) } } git2r/man/status.Rd0000644000176200001440000000314114704742556013703 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/status.R \name{status} \alias{status} \title{Status} \usage{ status( repo = ".", staged = TRUE, unstaged = TRUE, untracked = TRUE, ignored = FALSE, all_untracked = FALSE ) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{staged}{Include staged files. Default TRUE.} \item{unstaged}{Include unstaged files. Default TRUE.} \item{untracked}{Include untracked files and directories. Default TRUE.} \item{ignored}{Include ignored files. Default FALSE.} \item{all_untracked}{Shows individual files in untracked directories if \code{untracked} is \code{TRUE}.} } \value{ \code{git_status} with repository status } \description{ Display state of the repository working directory and the staging area. } \examples{ \dontrun{ ## Initialize a repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Config user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file writeLines("Hello world!", file.path(path, "test.txt")) ## Check status; untracked file status(repo) ## Add file add(repo, "test.txt") ## Check status; staged file status(repo) ## Commit commit(repo, "First commit message") ## Check status; clean status(repo) ## Change the file writeLines(c("Hello again!", "Here is a second line", "And a third"), file.path(path, "test.txt")) ## Check status; unstaged file status(repo) ## Add file and commit add(repo, "test.txt") commit(repo, "Second commit message") ## Check status; clean status(repo) } } git2r/man/is_local.Rd0000644000176200001440000000235214704742555014147 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/branch.R \name{is_local} \alias{is_local} \title{Check if branch is local} \usage{ is_local(branch) } \arguments{ \item{branch}{The branch \code{object} to check if it's local} } \value{ \code{TRUE} if branch is local, else \code{FALSE}. } \description{ Check if branch is local } \examples{ \dontrun{ ## Initialize repositories path_bare <- tempfile(pattern="git2r-") path_repo <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo) repo_bare <- init(path_bare, bare = TRUE) repo <- clone(path_bare, path_repo) ## Config first user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path_repo, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Push commits from repository to bare repository ## Adds an upstream tracking branch to branch 'master' push(repo, "origin", "refs/heads/master") ## List branches branches(repo) ## Check if first branch is_local is_local(branches(repo)[[1]]) ## Check if second branch is_local is_local(branches(repo)[[2]]) } } git2r/man/ls_tree.Rd0000644000176200001440000000375414704742556014027 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tree.R \name{ls_tree} \alias{ls_tree} \title{List the contents of a tree object} \usage{ ls_tree(tree = NULL, repo = ".", recursive = TRUE) } \arguments{ \item{tree}{default (\code{NULL}) is the tree of the last commit in \code{repo}. Can also be a \code{git_tree} object or a character that identifies a tree in the repository (see \sQuote{Examples}).} \item{repo}{never used if \code{tree} is a \code{git_tree} object. A \code{git_repository} object, or a path (default = '.') to a repository.} \item{recursive}{default is to recurse into sub-trees.} } \value{ A data.frame with the following columns: \describe{ \item{mode}{UNIX file attribute of the tree entry} \item{type}{type of object} \item{sha}{sha of the object} \item{path}{path relative to the root tree} \item{name}{filename of the tree entry} \item{len}{object size of blob (file) entries. NA for other objects.} } } \description{ Traverse the entries in a tree and its subtrees. Akin to the 'git ls-tree' command. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) dir.create(file.path(path, "subfolder")) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create three files and commit writeLines("First file", file.path(path, "example-1.txt")) writeLines("Second file", file.path(path, "subfolder/example-2.txt")) writeLines("Third file", file.path(path, "example-3.txt")) add(repo, c("example-1.txt", "subfolder/example-2.txt", "example-3.txt")) commit(repo, "Commit message") ## Traverse tree entries and its subtrees. ## Various approaches that give identical result. ls_tree(tree = tree(last_commit(path))) ls_tree(tree = tree(last_commit(repo))) ls_tree(repo = path) ls_tree(repo = repo) ## Skip content in subfolder ls_tree(repo = repo, recursive = FALSE) ## Start in subfolder ls_tree(tree = "HEAD:subfolder", repo = repo) } } git2r/man/is_tree.Rd0000644000176200001440000000150214704742556014011 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tree.R \name{is_tree} \alias{is_tree} \title{Check if object is S3 class git_tree} \usage{ is_tree(object) } \arguments{ \item{object}{Check if object is S3 class git_tree} } \value{ TRUE if object is S3 class git_tree, else FALSE } \description{ Check if object is S3 class git_tree } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Commit a text file writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "First commit message") tree_1 <- tree(commit_1) ## Check if tree is_tree(commit_1) is_tree(tree_1) } } \keyword{methods} git2r/man/git2r.Rd0000644000176200001440000000174514704742555013416 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/git2r.R \docType{package} \name{git2r} \alias{git2r} \alias{git2r-package} \title{git2r: R bindings to the libgit2 library} \description{ git2r: R bindings to the libgit2 library. } \seealso{ Useful links: \itemize{ \item \url{https://docs.ropensci.org/git2r/} \item \url{https://github.com/ropensci/git2r} \item Report bugs at \url{https://github.com/ropensci/git2r/issues} } } \author{ \strong{Maintainer}: Stefan Widgren \email{stefan.widgren@gmail.com} (\href{https://orcid.org/0000-0001-5745-2284}{ORCID}) Other contributors: \itemize{ \item Gabor Csardi [contributor] \item Gregory Jefferis [contributor] \item Jennifer Bryan [contributor] \item Jeroen Ooms [contributor] \item Jim Hester [contributor] \item John Blischak [contributor] \item Karthik Ram [contributor] \item Peter Carbonetto [contributor] \item Scott Chamberlain [contributor] \item Thomas Rosendal [contributor] } } git2r/man/reflog.Rd0000644000176200001440000000310614704742556013637 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/reflog.R \name{reflog} \alias{reflog} \title{List and view reflog information} \usage{ reflog(repo = ".", refname = "HEAD") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{refname}{The name of the reference to list. 'HEAD' by default.} } \value{ S3 class \code{git_reflog} with git_reflog_entry objects. } \description{ List and view reflog information } \examples{ \dontrun{ ## Initialize a repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Config user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Change file and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "Second commit message") ## Change file again and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", "minim veniam, quis nostrud exercitation ullamco laboris nisi ut") writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "Third commit message") ## View reflog reflog(repo) } } git2r/man/stash_pop.Rd0000644000176200001440000000276514704742556014373 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stash.R \name{stash_pop} \alias{stash_pop} \title{Pop stash} \usage{ stash_pop(object = ".", index = 1) } \arguments{ \item{object}{path to a repository, or a \code{git_repository} object, or the stash \code{object} to pop. Default is a \code{path = '.'} to a reposiory.} \item{index}{The index to the stash to pop. Only used when \code{object} is a path to a repository or a \code{git_repository} object. Default is \code{index = 1}.} } \value{ invisible NULL } \description{ Apply a single stashed state from the stash list and remove it from the list if successful. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) # Configure a user config(repo, user.name = "Alice", user.email = "alice@example.org") # Create a file, add and commit writeLines("Hello world!", file.path(path, "test.txt")) add(repo, 'test.txt') commit(repo, "Commit message") # Change file writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) # Create stash in repository stash(repo) # Change file writeLines(c("Hello world!", "HeLlO wOrLd!"), file.path(path, "test.txt")) # Create stash in repository stash(repo) # View stashes stash_list(repo) # Read file readLines(file.path(path, "test.txt")) # Pop latest git_stash object in repository stash_pop(stash_list(repo)[[1]]) # Read file readLines(file.path(path, "test.txt")) # View stashes stash_list(repo) } } git2r/man/branch_set_upstream.Rd0000644000176200001440000000275414704742555016420 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/branch.R \name{branch_set_upstream} \alias{branch_set_upstream} \title{Set remote tracking branch} \usage{ branch_set_upstream(branch = NULL, name) } \arguments{ \item{branch}{The branch to configure} \item{name}{remote-tracking or local branch to set as upstream. Pass NULL to unset.} } \value{ invisible NULL } \description{ Set the upstream configuration for a given local branch } \examples{ \dontrun{ ## Initialize two temporary repositories path_bare <- tempfile(pattern="git2r-") path_repo <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo) repo_bare <- init(path_bare, bare = TRUE) repo <- clone(path_bare, path_repo) ## Config user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path_repo, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Push commits from repository to bare repository ## Adds an upstream tracking branch to branch 'master' push(repo, "origin", "refs/heads/master") ## Unset remote remote tracking branch branch_get_upstream(repository_head(repo)) branch_set_upstream(repository_head(repo), NULL) branch_get_upstream(repository_head(repo)) ## Set remote tracking branch branch_set_upstream(repository_head(repo), "origin/master") branch_get_upstream(repository_head(repo)) } } git2r/man/diff-methods.Rd0000644000176200001440000001145114704742555014733 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/diff.R \name{diff.git_repository} \alias{diff.git_repository} \alias{diff.git_tree} \title{Changes between commits, trees, working tree, etc.} \usage{ \method{diff}{git_repository}( x, index = FALSE, as_char = FALSE, filename = NULL, context_lines = 3, interhunk_lines = 0, old_prefix = "a", new_prefix = "b", id_abbrev = NULL, path = NULL, max_size = NULL, ... ) \method{diff}{git_tree}( x, new_tree = NULL, index = FALSE, as_char = FALSE, filename = NULL, context_lines = 3, interhunk_lines = 0, old_prefix = "a", new_prefix = "b", id_abbrev = NULL, path = NULL, max_size = NULL, ... ) } \arguments{ \item{x}{A \code{git_repository} object or the old \code{git_tree} object to compare to.} \item{index}{\describe{ \item{\emph{When object equals a git_repository}}{ Whether to compare the index to HEAD. If FALSE (the default), then the working tree is compared to the index. } \item{\emph{When object equals a git_tree}}{ Whether to use the working directory (by default), or the index (if set to TRUE) in the comparison to \code{object}. } }} \item{as_char}{logical: should the result be converted to a character string?. Default is FALSE.} \item{filename}{If as_char is TRUE, then the diff can be written to a file with name filename (the file is overwritten if it exists). Default is NULL.} \item{context_lines}{The number of unchanged lines that define the boundary of a hunk (and to display before and after). Defaults to 3.} \item{interhunk_lines}{The maximum number of unchanged lines between hunk boundaries before the hunks will be merged into one. Defaults to 0.} \item{old_prefix}{The virtual "directory" prefix for old file names in hunk headers. Default is "a".} \item{new_prefix}{The virtual "directory" prefix for new file names in hunk headers. Defaults to "b".} \item{id_abbrev}{The abbreviation length to use when formatting object ids. Defaults to the value of 'core.abbrev' from the config, or 7 if NULL.} \item{path}{A character vector of paths / fnmatch patterns to constrain diff. Default is NULL which include all paths.} \item{max_size}{A size (in bytes) above which a blob will be marked as binary automatically; pass a negative value to disable. Defaults to 512MB when max_size is NULL.} \item{...}{Not used.} \item{new_tree}{The new git_tree object to compare, or NULL. If NULL, then we use the working directory or the index (see the \code{index} argument).} } \value{ A \code{git_diff} object if as_char is FALSE. If as_char is TRUE and filename is NULL, a character string, else NULL. } \description{ Changes between commits, trees, working tree, etc. } \section{Line endings}{ Different operating systems handle line endings differently. Windows uses both a carriage-return character and a linefeed character to represent a newline in a file. While Linux and macOS use only the linefeed character for a newline in a file. To avoid problems in your diffs, you can configure Git to properly handle line endings using the \verb{core.autocrlf} setting in the Git config file, see the Git documentation (\url{https://git-scm.com/}). } \examples{ \dontrun{ ## Initialize a repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Config user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add, commit writeLines("Hello world!", file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Commit message") ## Change the file writeLines(c("Hello again!", "Here is a second line", "And a third"), file.path(path, "test.txt")) ## diff between index and workdir diff_1 <- diff(repo) summary(diff_1) cat(diff(repo, as_char=TRUE)) ## Diff between index and HEAD is empty diff_2 <- diff(repo, index=TRUE) summary(diff_2) cat(diff(repo, index=TRUE, as_char=TRUE)) ## Diff between tree and working dir, same as diff_1 diff_3 <- diff(tree(commits(repo)[[1]])) summary(diff_3) cat(diff(tree(commits(repo)[[1]]), as_char=TRUE)) ## Add changes, diff between index and HEAD is the same as diff_1 add(repo, "test.txt") diff_4 <- diff(repo, index=TRUE) summary(diff_4) cat(diff(repo, index=TRUE, as_char=TRUE)) ## Diff between tree and index diff_5 <- diff(tree(commits(repo)[[1]]), index=TRUE) summary(diff_5) cat(diff(tree(commits(repo)[[1]]), index=TRUE, as_char=TRUE)) ## Diff between two trees commit(repo, "Second commit") tree_1 <- tree(commits(repo)[[2]]) tree_2 <- tree(commits(repo)[[1]]) diff_6 <- diff(tree_1, tree_2) summary(diff_6) cat(diff(tree_1, tree_2, as_char=TRUE)) ## Binary files set.seed(42) writeBin(as.raw((sample(0:255, 1000, replace=TRUE))), con=file.path(path, "test.bin")) add(repo, "test.bin") diff_7 <- diff(repo, index=TRUE) summary(diff_7) cat(diff(repo, index=TRUE, as_char=TRUE)) } } git2r/man/push.Rd0000644000176200001440000000511414704742556013341 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/push.R \name{push} \alias{push} \title{Push} \usage{ push( object = ".", name = NULL, refspec = NULL, force = FALSE, credentials = NULL, set_upstream = FALSE ) } \arguments{ \item{object}{path to repository, or a \code{git_repository} or \code{git_branch}.} \item{name}{The remote's name. Default is NULL.} \item{refspec}{The refspec to be pushed. Default is NULL.} \item{force}{Force your local revision to the remote repo. Use it with care. Default is FALSE.} \item{credentials}{The credentials for remote repository access. Default is NULL. To use and query an ssh-agent for the ssh key credentials, let this parameter be NULL (the default).} \item{set_upstream}{Set the current local branch to track the remote branch. Default is FALSE.} } \value{ invisible(NULL) } \description{ Push } \examples{ \dontrun{ ## Initialize two temporary repositories path_bare <- tempfile(pattern="git2r-") path_repo <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo) repo_bare <- init(path_bare, bare = TRUE) ## Clone the bare repository. This creates remote-tracking ## branches for each branch in the cloned repository. repo <- clone(path_bare, path_repo) ## Config user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path_repo, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Push commits from repository to bare repository push(repo, "origin", "refs/heads/master") ## Now, unset the remote-tracking branch to NULL to demonstrate ## the 'set_upstream' argument. Then push with 'set_upstream = TRUE' ## to add the upstream tracking branch to branch 'master' again. branch_get_upstream(repository_head(repo)) branch_set_upstream(repository_head(repo), NULL) branch_get_upstream(repository_head(repo)) push(repo, "origin", "refs/heads/master", set_upstream = TRUE) branch_get_upstream(repository_head(repo)) ## Change file and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path_repo, "example.txt")) add(repo, "example.txt") commit(repo, "Second commit message") ## Push commits from repository to bare repository push(repo) ## List commits in repository and bare repository commits(repo) commits(repo_bare) } } \seealso{ \code{\link{cred_user_pass}}, \code{\link{cred_ssh_key}} } git2r/man/bundle_r_package.Rd0000644000176200001440000000226114704742555015626 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/bundle_r_package.R \name{bundle_r_package} \alias{bundle_r_package} \title{Bundle bare repo of package} \usage{ bundle_r_package(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ Invisible bundled \code{git_repository} object } \description{ Clone the package git repository as a bare repository to \code{pkg/inst/pkg.git} } \examples{ \dontrun{ ## Initialize repository path <- tempfile() dir.create(path) path <- file.path(path, "git2r") repo <- clone("https://github.com/ropensci/git2r.git", path) ## Bundle bare repository in package bundle_r_package(repo) ## Build and install bundled package wd <- setwd(dirname(path)) system(sprintf("R CMD build \%s", path)) pkg <- list.files(".", pattern = "[.]tar[.]gz$") system(sprintf("R CMD INSTALL \%s", pkg)) setwd(wd) ## Reload package detach("package:git2r", unload = TRUE) library(git2r) ## Summarize last five commits of bundled repo repo <- repository(system.file("git2r.git", package = "git2r")) invisible(lapply(commits(repo, n = 5), summary)) ## Plot content of bundled repo plot(repo) } } git2r/man/remote_remove.Rd0000644000176200001440000000235714704742556015240 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/remote.R \name{remote_remove} \alias{remote_remove} \title{Remove a remote} \usage{ remote_remove(repo = ".", name = NULL) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{name}{The name of the remote to remove} } \value{ NULL, invisibly } \description{ All remote-tracking branches and configuration settings for the remote will be removed. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name="Alice", user.email="alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Add a remote remote_add(repo, "playground", "https://example.org/git2r/playground") remotes(repo) remote_url(repo, "playground") ## Rename a remote remote_rename(repo, "playground", "foobar") remotes(repo) remote_url(repo, "foobar") ## Set remote url remote_set_url(repo, "foobar", "https://example.org/git2r/foobar") remotes(repo) remote_url(repo, "foobar") ## Remove a remote remote_remove(repo, "foobar") remotes(repo) } } git2r/man/checkout.Rd0000644000176200001440000000603114704742555014165 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/checkout.R \name{checkout} \alias{checkout} \title{Checkout} \usage{ checkout( object = NULL, branch = NULL, create = FALSE, force = FALSE, path = NULL, ... ) } \arguments{ \item{object}{A path to a repository, or a \code{git_repository} object, or a \code{git_commit} object, or a \code{git_tag} object, or a \code{git_tree} object.} \item{branch}{name of the branch to check out. Only used if object is a path to a repository or a \code{git_repository} object.} \item{create}{create branch if it doesn't exist. Only used if object is a path to a repository or a \code{git_repository} object.} \item{force}{If \code{TRUE}, then make working directory match target. This will throw away local changes. Default is \code{FALSE}.} \item{path}{Limit the checkout operation to only certain paths. This argument is only used if branch is NULL. Default is \code{NULL}.} \item{...}{Additional arguments. Not used.} } \value{ invisible NULL } \description{ Update files in the index and working tree to match the content of the tree pointed at by the treeish object (commit, tag or tree). The default checkout strategy (\code{force = FALSE}) will only make modifications that will not lose changes. Use \code{force = TRUE} to force working directory to look like index. } \examples{ \dontrun{ ## Create directories and initialize repositories path_bare <- tempfile(pattern="git2r-") path_repo_1 <- tempfile(pattern="git2r-") path_repo_2 <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo_1) dir.create(path_repo_2) repo_bare <- init(path_bare, bare = TRUE) ## Clone to repo 1 and config user repo_1 <- clone(path_bare, path_repo_1) config(repo_1, user.name = "Alice", user.email = "alice@example.org") ## Add changes to repo 1 and push to bare lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path_repo_1, "test.txt")) add(repo_1, "test.txt") commit(repo_1, "First commit message") push(repo_1, "origin", "refs/heads/master") ## Create and checkout 'dev' branch in repo 1 checkout(repo_1, "dev", create = TRUE) ## Add changes to 'dev' branch in repo 1 and push to bare lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path_repo_1, "test.txt")) add(repo_1, "test.txt") commit(repo_1, "Second commit message") push(repo_1, "origin", "refs/heads/dev") ## Clone to repo 2 repo_2 <- clone(path_bare, path_repo_2) config(repo_2, user.name = "Bob", user.email = "bob@example.org") ## Read content of 'test.txt' readLines(file.path(path_repo_2, "test.txt")) ## Checkout dev branch checkout(repo_2, "dev") ## Read content of 'test.txt' readLines(file.path(path_repo_2, "test.txt")) ## Edit "test.txt" in repo_2 writeLines("Hello world!", con = file.path(path_repo_2, "test.txt")) ## Check status status(repo_2) ## Checkout "test.txt" checkout(repo_2, path = "test.txt") ## Check status status(repo_2) } } git2r/man/remote_ls.Rd0000644000176200001440000000166614704742556014363 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/remote.R \name{remote_ls} \alias{remote_ls} \title{List references in a remote repository} \usage{ remote_ls(name = NULL, repo = NULL, credentials = NULL) } \arguments{ \item{name}{Character vector with the "remote" repository URL to query or the name of the remote if a \code{repo} argument is given.} \item{repo}{an optional repository object used if remotes are specified by name.} \item{credentials}{The credentials for remote repository access. Default is NULL. To use and query an ssh-agent for the ssh key credentials, let this parameter be NULL (the default).} } \value{ Character vector for each reference with the associated commit IDs. } \description{ Displays references available in a remote repository along with the associated commit IDs. Akin to the 'git ls-remote' command. } \examples{ \dontrun{ remote_ls("https://github.com/ropensci/git2r") } } git2r/man/remote_add.Rd0000644000176200001440000000234514704742556014470 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/remote.R \name{remote_add} \alias{remote_add} \title{Add a remote to a repo} \usage{ remote_add(repo = ".", name = NULL, url = NULL) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{name}{Short name of the remote repository} \item{url}{URL of the remote repository} } \value{ NULL, invisibly } \description{ Add a remote to a repo } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name="Alice", user.email="alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Add a remote remote_add(repo, "playground", "https://example.org/git2r/playground") remotes(repo) remote_url(repo, "playground") ## Rename a remote remote_rename(repo, "playground", "foobar") remotes(repo) remote_url(repo, "foobar") ## Set remote url remote_set_url(repo, "foobar", "https://example.org/git2r/foobar") remotes(repo) remote_url(repo, "foobar") ## Remove a remote remote_remove(repo, "foobar") remotes(repo) } } git2r/man/when.Rd0000644000176200001440000000331314704742556013322 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/when.R \name{when} \alias{when} \title{When} \usage{ when(object, tz = "GMT", origin = "1970-01-01", usetz = TRUE) } \arguments{ \item{object}{the \code{object} to extract the time slot from.} \item{tz}{a character string. The time zone specification to be used for the conversion, \emph{if one is required}. System-specific (see \link[base]{time zones}), but \code{""} is the current time zone, and \code{"GMT"} is UTC (Universal Time, Coordinated). Invalid values are most commonly treated as UTC, on some platforms with a warning.} \item{origin}{a date-time object, or something which can be coerced by \code{as.POSIXct(tz = "GMT")} to such an object. Optional since \R 4.3.0, where the equivalent of \code{"1970-01-01"} is used.} \item{usetz}{logical. Should the time zone abbreviation be appended to the output? This is used in printing times, and more reliable than using \code{"\%Z"}.} } \value{ A \code{character} vector of length one. } \description{ Help method to extract the time as a character string from a git_commit, git_signature, git_tag and git_time object. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a first user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Create tag tag(repo, "Tagname", "Tag message") when(commits(repo)[[1]]) when(tags(repo)[[1]]) when(tags(repo)[[1]], tz = Sys.timezone()) } } \seealso{ \code{\link{git_time}} } git2r/man/content.Rd0000644000176200001440000000176114704742555014037 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/blob.R \name{content} \alias{content} \title{Content of blob} \usage{ content(blob = NULL, split = TRUE, raw = FALSE) } \arguments{ \item{blob}{The blob object.} \item{split}{Split blob content to text lines. Default TRUE.} \item{raw}{When \code{TRUE}, get the content of the blob as a raw vector, else as a character vector. Default is \code{FALSE}.} } \value{ The content of the blob. NA_character_ if the blob is binary and \code{raw} is \code{FALSE}. } \description{ Content of blob } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Display content of blob. content(tree(commits(repo)[[1]])["example.txt"]) } } git2r/man/index_remove_bypath.Rd0000644000176200001440000000237614704742555016423 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/index.R \name{index_remove_bypath} \alias{index_remove_bypath} \title{Remove an index entry corresponding to a file on disk} \usage{ index_remove_bypath(repo = ".", path = NULL) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{path}{character vector with filenames to remove. The path must be relative to the repository's working folder. It may exist. If this file currently is the result of a merge conflict, this file will no longer be marked as conflicting. The data about the conflict will be moved to the "resolve undo" (REUC) section.} } \value{ invisible(NULL) } \description{ Remove an index entry corresponding to a file on disk } \examples{ \dontrun{ ## Initialize a repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file writeLines("Hello world!", file.path(path, "file-to-remove.txt")) ## Add file to repository add(repo, "file-to-remove.txt") ## View status of repository status(repo) ## Remove file index_remove_bypath(repo, "file-to-remove.txt") ## View status of repository status(repo) } } git2r/man/branch_create.Rd0000644000176200001440000000262114704742555015141 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/branch.R \name{branch_create} \alias{branch_create} \title{Create a branch} \usage{ branch_create(commit = last_commit(), name = NULL, force = FALSE) } \arguments{ \item{commit}{Commit to which the branch should point. The default is to use the \code{last_commit()} function to determine the commit to which the branch should point.} \item{name}{Name for the branch} \item{force}{Overwrite existing branch. Default = FALSE} } \value{ invisible git_branch object } \description{ Create a branch } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") lines <- "Hello world!" writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "First commit message") ## Create a branch branch_1 <- branch_create(commit_1, name = "test-branch") ## Add one more commit lines <- c("Hello world!", "HELLO WORLD!") writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit_2 <- commit(repo, "Another commit message") ## Create a branch with the same name should fail try(branch_create(commit_2, name = "test-branch"), TRUE) ## Force it branch_2 <- branch_create(commit_2, name = "test-branch", force = TRUE) } } git2r/man/length.git_blob.Rd0000644000176200001440000000151414704742555015422 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/blob.R \name{length.git_blob} \alias{length.git_blob} \title{Size in bytes of the contents of a blob} \usage{ \method{length}{git_blob}(x) } \arguments{ \item{x}{The blob \code{object}} } \value{ a non-negative integer } \description{ Size in bytes of the contents of a blob } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Commit a text file writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "First commit message") blob_1 <- tree(commit_1)["example.txt"] ## Get length in size of bytes of the content of the blob length(blob_1) } } git2r/man/note_remove.Rd0000644000176200001440000000244114704742556014704 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/note.R \name{note_remove} \alias{note_remove} \title{Remove the note for an object} \usage{ note_remove(note = NULL, author = NULL, committer = NULL) } \arguments{ \item{note}{The note to remove} \item{author}{Signature of the notes commit author.} \item{committer}{Signature of the notes commit committer.} } \value{ invisible NULL } \description{ Remove the note for an object } \examples{ \dontrun{ ## Create and initialize a repository in a temporary directory path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "Commit message 1") ## Create note in default namespace note_1 <- note_create(commit_1, "Note-1") ## Create note in named (review) namespace note_2 <- note_create(commit_1, "Note-2", ref="refs/notes/review") ## List notes in default namespace notes(repo) ## List notes in 'review' namespace notes(repo, "review") ## Remove notes note_remove(note_1) note_remove(note_2) ## List notes in default namespace notes(repo) ## List notes in 'review' namespace notes(repo, "review") } } git2r/man/config.Rd0000644000176200001440000000271314704742555013630 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/config.R \name{config} \alias{config} \title{Config} \usage{ config(repo = NULL, global = FALSE, user.name, user.email, ...) } \arguments{ \item{repo}{The \code{repository}. Default is NULL.} \item{global}{Write option(s) to global configuration file. Default is FALSE.} \item{user.name}{The user name. Use NULL to delete the entry} \item{user.email}{The e-mail address. Use NULL to delete the entry} \item{...}{Additional options to write or delete from the configuration.} } \value{ S3 class \code{git_config}. When writing options, the configuration is returned invisible. } \description{ Config file management. To display the configuration variables, call method \code{config} without the \code{user.name}, \code{user.email} or \code{...} options. } \details{ There are two ways git2r can find the local repository when writing local options (1) Use the \code{repo} argument. (2) If the \code{repo} argument is \code{NULL} but the current working directory is inside the local repository, then \code{git2r} uses that repository. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern = "git2r-") dir.create(path) repo <- init(path) ## Set user name and email. config(repo, user.name = "Alice", user.email = "alice@example.org") ## Display configuration config(repo) ## Delete user email. config(repo, user.email = NULL) ## Display configuration config(repo) } } git2r/man/tree.Rd0000644000176200001440000000130714704742556013321 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tree.R \name{tree} \alias{tree} \title{Tree} \usage{ tree(object = NULL) } \arguments{ \item{object}{the \code{commit} or \code{stash} object} } \value{ A S3 class git_tree object } \description{ Get the tree pointed to by a commit or stash. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a first user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") tree(last_commit(repo)) } } git2r/man/branches.Rd0000644000176200001440000000235114704742555014146 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/branch.R \name{branches} \alias{branches} \title{Branches} \usage{ branches(repo = ".", flags = c("all", "local", "remote")) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{flags}{Filtering flags for the branch listing. Valid values are 'all', 'local' or 'remote'} } \value{ list of branches in repository } \description{ List branches in repository } \examples{ \dontrun{ ## Initialize repositories path_bare <- tempfile(pattern="git2r-") path_repo <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo) repo_bare <- init(path_bare, bare = TRUE) repo <- clone(path_bare, path_repo) ## Config first user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path_repo, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Push commits from repository to bare repository ## Adds an upstream tracking branch to branch 'master' push(repo, "origin", "refs/heads/master") ## List branches branches(repo) } } git2r/man/summary.git_tree.Rd0000644000176200001440000000142114704742556015655 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tree.R \name{summary.git_tree} \alias{summary.git_tree} \title{Summary of tree} \usage{ \method{summary}{git_tree}(object, ...) } \arguments{ \item{object}{The tree \code{object}} \item{...}{Additional arguments affecting the summary produced.} } \value{ None (invisible 'NULL'). } \description{ Summary of tree } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") summary(tree(last_commit(repo))) } } git2r/man/ahead_behind.Rd0000644000176200001440000000307014704742555014733 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/commit.R \name{ahead_behind} \alias{ahead_behind} \title{Ahead Behind} \usage{ ahead_behind(local = NULL, upstream = NULL) } \arguments{ \item{local}{a git_commit object. Can also be a tag or a branch, and in that case the commit will be the target of the tag or branch.} \item{upstream}{a git_commit object. Can also be a tag or a branch, and in that case the commit will be the target of the tag or branch.} } \value{ An integer vector of length 2 with number of commits that the upstream commit is ahead and behind the local commit } \description{ Count the number of unique commits between two commit objects. } \examples{ \dontrun{ ## Create a directory in tempdir path <- tempfile(pattern="git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "test.txt")) add(repo, "test.txt") commit_1 <- commit(repo, "Commit message 1") tag_1 <- tag(repo, "Tagname1", "Tag message 1") # Change file and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path, "test.txt")) add(repo, "test.txt") commit_2 <- commit(repo, "Commit message 2") tag_2 <- tag(repo, "Tagname2", "Tag message 2") ahead_behind(commit_1, commit_2) ahead_behind(tag_1, tag_2) } } git2r/man/ssh_path.Rd0000644000176200001440000000152614704742555014175 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/credential.R \name{ssh_path} \alias{ssh_path} \title{Compose usual path to ssh keys} \usage{ ssh_path(file = "") } \arguments{ \item{file}{basename of file for which path is requested} } \value{ Full path to the file } \description{ This function provides a consistent means across OS-types to access the \code{.ssh} directory. } \details{ On Windows-based systems, \code{path.expand("~")} returns \code{"C:/Users/username/Documents"}, whereas the usual path to the \code{.ssh} directory is \code{"C:/Users/username"}. On other operating systems, \code{path.expand("~")} returns the usual path to the \code{.ssh} directory. Calling \code{ssh_path()} with no arguments will return the usual path to the \code{.ssh} directory. } \examples{ ssh_path() ssh_path("is_rsa.pub") } git2r/man/stash_drop.Rd0000644000176200001440000000257014704742556014533 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stash.R \name{stash_drop} \alias{stash_drop} \title{Drop stash} \usage{ stash_drop(object = ".", index = 1) } \arguments{ \item{object}{path to a repository, or a \code{git_repository} object, or the stash \code{object} to drop. Default is a \code{path = '.'} to a reposiory.} \item{index}{The index to the stash to drop. Only used when \code{object} is a path to a repository or a \code{git_repository} object. Default is \code{index = 1}.} } \value{ invisible NULL } \description{ Drop stash } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) # Configure a user config(repo, user.name = "Alice", user.email = "alice@example.org") # Create a file, add and commit writeLines("Hello world!", file.path(path, "test.txt")) add(repo, 'test.txt') commit(repo, "Commit message") # Change file writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) # Create stash in repository stash(repo) # Change file writeLines(c("Hello world!", "HeLlO wOrLd!"), file.path(path, "test.txt")) # Create stash in repository stash(repo) # View stashes stash_list(repo) # Drop git_stash object in repository stash_drop(stash_list(repo)[[1]]) ## Drop stash using an index to stash stash_drop(repo, 1) # View stashes stash_list(repo) } } git2r/man/rm_file.Rd0000644000176200001440000000174414704742555014003 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/index.R \name{rm_file} \alias{rm_file} \title{Remove files from the working tree and from the index} \usage{ rm_file(repo = ".", path = NULL) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{path}{character vector with filenames to remove. Only files known to Git are removed.} } \value{ invisible(NULL) } \description{ Remove files from the working tree and from the index } \examples{ \dontrun{ ## Initialize a repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file writeLines("Hello world!", file.path(path, "file-to-remove.txt")) ## Add file to repository add(repo, "file-to-remove.txt") commit(repo, "First commit message") ## Remove file rm_file(repo, "file-to-remove.txt") ## View status of repository status(repo) } } git2r/man/parents.Rd0000644000176200001440000000171614704742555014041 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/commit.R \name{parents} \alias{parents} \title{Parents} \usage{ parents(object = NULL) } \arguments{ \item{object}{a git_commit object.} } \value{ list of git_commit objects } \description{ Get parents of a commit. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") writeLines("First line.", file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "First commit message") ## commit_1 has no parents parents(commit_1) ## Update 'example.txt' and commit writeLines(c("First line.", "Second line."), file.path(path, "example.txt")) add(repo, "example.txt") commit_2 <- commit(repo, "Second commit message") ## commit_2 has commit_1 as parent parents(commit_2) } } git2r/man/is_merge.Rd0000644000176200001440000000340014704742555014147 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/commit.R \name{is_merge} \alias{is_merge} \title{Is merge} \usage{ is_merge(commit = NULL) } \arguments{ \item{commit}{a git_commit object.} } \value{ TRUE if commit has more than one parent, else FALSE } \description{ Determine if a commit is a merge commit, i.e. has more than one parent. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") writeLines(c("First line in file 1.", "Second line in file 1."), file.path(path, "example-1.txt")) add(repo, "example-1.txt") commit(repo, "First commit message") ## Create and add one more file writeLines(c("First line in file 2.", "Second line in file 2."), file.path(path, "example-2.txt")) add(repo, "example-2.txt") commit(repo, "Second commit message") ## Create a new branch 'fix' checkout(repo, "fix", create = TRUE) ## Update 'example-1.txt' (swap words in first line) and commit writeLines(c("line First in file 1.", "Second line in file 1."), file.path(path, "example-1.txt")) add(repo, "example-1.txt") commit(repo, "Third commit message") checkout(repo, "master") ## Update 'example-2.txt' (swap words in second line) and commit writeLines(c("First line in file 2.", "line Second in file 2."), file.path(path, "example-2.txt")) add(repo, "example-2.txt") commit(repo, "Fourth commit message") ## Merge 'fix' merge(repo, "fix") ## Display parents of last commit parents(lookup(repo, branch_target(repository_head(repo)))) ## Check that last commit is a merge is_merge(lookup(repo, branch_target(repository_head(repo)))) } } git2r/man/odb_objects.Rd0000644000176200001440000000207114704742556014636 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/odb.R \name{odb_objects} \alias{odb_objects} \title{List all objects available in the database} \usage{ odb_objects(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ A data.frame with the following columns: \describe{ \item{sha}{The sha of the object} \item{type}{The type of the object} \item{len}{The length of the object} } } \description{ List all objects available in the database } \examples{ \dontrun{ ## Create a directory in tempdir path <- tempfile(pattern="git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Commit message 1") ## Create tag tag(repo, "Tagname", "Tag message") ## List objects in repository odb_objects(repo) } } git2r/man/reset.Rd0000644000176200001440000000452014704742556013504 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/reset.R \name{reset} \alias{reset} \title{Reset current HEAD to the specified state} \usage{ reset(object, reset_type = c("soft", "mixed", "hard"), path = NULL) } \arguments{ \item{object}{Either a \code{git_commit}, a \code{git_repository} or a character vector. If \code{object} is a \code{git_commit}, HEAD is moved to the \code{git_commit}. If \code{object} is a \code{git_repository}, resets the index entries in the \code{path} argument to their state at HEAD. If \code{object} is a character vector with paths, resets the index entries in \code{object} to their state at HEAD if the current working directory is in a repository.} \item{reset_type}{If object is a 'git_commit', the kind of reset operation to perform. 'soft' means the HEAD will be moved to the commit. 'mixed' reset will trigger a 'soft' reset, plus the index will be replaced with the content of the commit tree. 'hard' reset will trigger a 'mixed' reset and the working directory will be replaced with the content of the index.} \item{path}{If object is a 'git_repository', resets the index entries for all paths to their state at HEAD.} } \value{ invisible NULL } \description{ Reset current HEAD to the specified state } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) # Configure a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit writeLines("Hello world!", file.path(path, "test-1.txt")) add(repo, "test-1.txt") commit_1 <- commit(repo, "Commit message") ## Change and stage the file writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test-1.txt")) add(repo, "test-1.txt") status(repo) ## Unstage file reset(repo, path = "test-1.txt") status(repo) ## Make one more commit add(repo, "test-1.txt") commit(repo, "Next commit message") ## Create one more file writeLines("Hello world!", file.path(path, "test-2.txt")) ## 'soft' reset to first commit and check status reset(commit_1) status(repo) ## 'mixed' reset to first commit and check status commit(repo, "Next commit message") reset(commit_1, "mixed") status(repo) ## 'hard' reset to first commit and check status add(repo, "test-1.txt") commit(repo, "Next commit message") reset(commit_1, "hard") status(repo) } } git2r/man/hashfile.Rd0000644000176200001440000000141314704742555014142 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/blob.R \name{hashfile} \alias{hashfile} \title{Determine the sha from a blob in a file} \usage{ hashfile(path = NULL) } \arguments{ \item{path}{The path vector with files to hash.} } \value{ A vector with the sha for each file in path. } \description{ The blob is not written to the object database. } \examples{ \dontrun{ ## Create a file. NOTE: The line endings from writeLines gives ## LF (line feed) on Unix/Linux and CRLF (carriage return, line feed) ## on Windows. The example use writeChar to have more control. path <- tempfile() f <- file(path, "wb") writeChar("Hello, world!\n", f, eos = NULL) close(f) ## Generate hash hashfile(path) identical(hashfile(path), hash("Hello, world!\n")) } } git2r/man/is_tag.Rd0000644000176200001440000000145614704742556013635 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tag.R \name{is_tag} \alias{is_tag} \title{Check if object is a git_tag object} \usage{ is_tag(object) } \arguments{ \item{object}{Check if object is a git_tag object} } \value{ TRUE if object is a git_tag, else FALSE } \description{ Check if object is a git_tag object } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Commit a text file writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Create tag tag(repo, "Tagname", "Tag message") is_tag(tags(repo)[[1]]) is_tag(last_commit(repo)) } } git2r/man/contributions.Rd0000644000176200001440000000457414704742555015274 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/contributions.R \name{contributions} \alias{contributions} \title{Contributions} \usage{ contributions( repo = ".", breaks = c("month", "year", "quarter", "week", "day"), by = c("commits", "author") ) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{breaks}{Default is \code{month}. Change to year, quarter, week or day as necessary.} \item{by}{Contributions by "commits" or "author". Default is "commits".} } \value{ A \code{data.frame} with contributions. } \description{ See contributions to a Git repo } \examples{ \dontrun{ ## Create directories and initialize repositories path_bare <- tempfile(pattern="git2r-") path_repo_1 <- tempfile(pattern="git2r-") path_repo_2 <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo_1) dir.create(path_repo_2) repo_bare <- init(path_bare, bare = TRUE) ## Clone to repo 1 and config user repo_1 <- clone(path_bare, path_repo_1) config(repo_1, user.name = "Alice", user.email = "alice@example.org") ## Add changes to repo 1 and push to bare lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path_repo_1, "test.txt")) add(repo_1, "test.txt") commit(repo_1, "First commit message") ## Add more changes to repo 1 lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path_repo_1, "test.txt")) add(repo_1, "test.txt") commit(repo_1, "Second commit message") ## Push to bare push(repo_1, "origin", "refs/heads/master") ## Clone to repo 2 repo_2 <- clone(path_bare, path_repo_2) config(repo_2, user.name = "Bob", user.email = "bob@example.org") ## Add changes to repo 2 lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", "minim veniam, quis nostrud exercitation ullamco laboris nisi ut") writeLines(lines, file.path(path_repo_2, "test.txt")) add(repo_2, "test.txt") commit(repo_2, "Third commit message") ## Push to bare push(repo_2, "origin", "refs/heads/master") ## Pull changes to repo 1 pull(repo_1) ## View contributions by day contributions(repo_1) ## View contributions by author and day contributions(repo_1, by = "author") } } git2r/man/as.list.git_tree.Rd0000644000176200001440000000222114704742556015534 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tree.R \name{as.list.git_tree} \alias{as.list.git_tree} \title{Coerce entries in a git_tree to a list of entry objects} \usage{ \method{as.list}{git_tree}(x, ...) } \arguments{ \item{x}{The tree \code{object}} \item{...}{Unused} } \value{ list of entry objects } \description{ Coerce entries in a git_tree to a list of entry objects } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) dir.create(file.path(path, "subfolder")) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create three files and commit writeLines("First file", file.path(path, "example-1.txt")) writeLines("Second file", file.path(path, "subfolder/example-2.txt")) writeLines("Third file", file.path(path, "example-3.txt")) add(repo, c("example-1.txt", "subfolder/example-2.txt", "example-3.txt")) commit(repo, "Commit message") ## Inspect size of each blob in tree invisible(lapply(as(tree(last_commit(repo)), "list"), function(obj) { if (is_blob(obj)) summary(obj) NULL })) } } git2r/man/branch_get_upstream.Rd0000644000176200001440000000230614704742555016375 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/branch.R \name{branch_get_upstream} \alias{branch_get_upstream} \title{Get remote tracking branch} \usage{ branch_get_upstream(branch = NULL) } \arguments{ \item{branch}{The branch} } \value{ \code{git_branch} object or NULL if no remote tracking branch. } \description{ Get remote tracking branch, given a local branch. } \examples{ \dontrun{ ## Initialize two temporary repositories path_bare <- tempfile(pattern="git2r-") path_repo <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo) repo_bare <- init(path_bare, bare = TRUE) repo <- clone(path_bare, path_repo) ## Config user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path_repo, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Push commits from repository to bare repository ## Adds an upstream tracking branch to branch 'master' push(repo, "origin", "refs/heads/master") ## Get remote tracking branch branch_get_upstream(repository_head(repo)) } } git2r/man/commit.Rd0000644000176200001440000000317614704742555013657 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/commit.R \name{commit} \alias{commit} \title{Commit} \usage{ commit( repo = ".", message = NULL, all = FALSE, session = FALSE, author = NULL, committer = NULL ) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{message}{The commit message.} \item{all}{Stage modified and deleted files. Files not added to Git are not affected.} \item{session}{Add sessionInfo to commit message. Default is FALSE.} \item{author}{Signature with author and author time of commit.} \item{committer}{Signature with committer and commit time of commit.} } \value{ A list of class \code{git_commit} with entries: \describe{ \item{sha}{ The 40 character hexadecimal string of the SHA-1 } \item{author}{ An author signature } \item{committer}{ The committer signature } \item{summary}{ The short "summary" of a git commit message, comprising the first paragraph of the message with whitespace trimmed and squashed. } \item{message}{ The message of a commit } \item{repo}{ The \code{git_repository} object that contains the commit } } } \description{ Commit } \examples{ \dontrun{ ## Initialize a repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Config user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") } } git2r/man/git_config_files.Rd0000644000176200001440000000230114704742555015646 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/config.R \name{git_config_files} \alias{git_config_files} \title{Locate the path to configuration files} \usage{ git_config_files(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ a \code{data.frame} with one row per potential configuration file where \code{NA} means not found. } \description{ Potential configuration files: \describe{ \item{system}{ Locate the path to the system configuration file. If '/etc/gitconfig' doesn't exist, it will look for '\%PROGRAMFILES\%'. } \item{xdg}{ Locate the path to the global xdg compatible configuration file. The xdg compatible configuration file is usually located in '$HOME/.config/git/config'. This method will try to guess the full path to that file, if the file exists. } \item{global}{ The user or global configuration file is usually located in '$HOME/.gitconfig'. This method will try to guess the full path to that file, if the file exists. } \item{local}{ Locate the path to the repository specific configuration file, if the file exists. } } } git2r/man/as.data.frame.git_repository.Rd0000644000176200001440000000306514704742556020052 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{as.data.frame.git_repository} \alias{as.data.frame.git_repository} \title{Coerce Git repository to a \code{data.frame}} \usage{ \method{as.data.frame}{git_repository}(x, ...) } \arguments{ \item{x}{The repository \code{object}} \item{...}{Additional arguments. Not used.} } \value{ \code{data.frame} } \description{ The commits in the repository are coerced to a \code{data.frame} } \details{ The \code{data.frame} have the following columns: \describe{ \item{sha}{ The 40 character hexadecimal string of the SHA-1 } \item{summary}{ the short "summary" of the git commit message. } \item{message}{ the full message of a commit } \item{author}{ full name of the author } \item{email}{ email of the author } \item{when}{ time when the commit happened } } } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create three files and commit writeLines("First file", file.path(path, "example-1.txt")) writeLines("Second file", file.path(path, "example-2.txt")) writeLines("Third file", file.path(path, "example-3.txt")) add(repo, "example-1.txt") commit(repo, "Commit first file") add(repo, "example-2.txt") commit(repo, "Commit second file") add(repo, "example-3.txt") commit(repo, "Commit third file") ## Coerce commits to a data.frame df <- as.data.frame(repo) df } } git2r/man/branch_rename.Rd0000644000176200001440000000173214704742555015147 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/branch.R \name{branch_rename} \alias{branch_rename} \title{Rename a branch} \usage{ branch_rename(branch = NULL, name = NULL, force = FALSE) } \arguments{ \item{branch}{Branch to rename} \item{name}{The new name for the branch} \item{force}{Overwrite existing branch. Default is FALSE} } \value{ invisible renamed \code{git_branch} object } \description{ Rename a branch } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Config user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Rename 'master' branch to 'dev' branches(repo) branch_rename(repository_head(repo), "dev") branches(repo) } } git2r/man/remote_url.Rd0000644000176200001440000000247414704742556014545 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/remote.R \name{remote_url} \alias{remote_url} \title{Get the remote url for remotes in a repo} \usage{ remote_url(repo = ".", remote = NULL) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{remote}{Character vector with the remotes to get the url from. Default is the remotes of the repository.} } \value{ Character vector with remote_url for each of the remote } \description{ Get the remote url for remotes in a repo } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name="Alice", user.email="alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Add a remote remote_add(repo, "playground", "https://example.org/git2r/playground") remotes(repo) remote_url(repo, "playground") ## Rename a remote remote_rename(repo, "playground", "foobar") remotes(repo) remote_url(repo, "foobar") ## Set remote url remote_set_url(repo, "foobar", "https://example.org/git2r/foobar") remotes(repo) remote_url(repo, "foobar") ## Remove a remote remote_remove(repo, "foobar") remotes(repo) } } git2r/man/note_default_ref.Rd0000644000176200001440000000133714704742555015671 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/note.R \name{note_default_ref} \alias{note_default_ref} \title{Default notes reference} \usage{ note_default_ref(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ Character vector of length one with name of default notes reference } \description{ Get the default notes reference for a repository } \examples{ \dontrun{ ## Create and initialize a repository in a temporary directory path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## View default notes reference note_default_ref(repo) } } git2r/man/cred_user_pass.Rd0000644000176200001440000000214614704742555015364 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/credential.R \name{cred_user_pass} \alias{cred_user_pass} \title{Create a new plain-text username and password credential object} \usage{ cred_user_pass(username = NULL, password = NULL) } \arguments{ \item{username}{The username of the credential} \item{password}{The password of the credential. If getPass is installed and the only input is username, \code{getPass::getPass()} will be called to allow for interactive and obfuscated interactive input of the password.} } \value{ A list of class \code{cred_user_pass} with entries: \describe{ \item{username}{ The username of the credential } \item{password}{ The password of the credential } } } \description{ Create a new plain-text username and password credential object } \examples{ \dontrun{ ## Create a plain-text username and password credential object cred_user_pass("Random Developer", "SecretPassword") } } \seealso{ Other git credential functions: \code{\link{cred_env}()}, \code{\link{cred_ssh_key}()}, \code{\link{cred_token}()} } \concept{git credential functions} git2r/man/branch_delete.Rd0000644000176200001440000000144414704742555015142 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/branch.R \name{branch_delete} \alias{branch_delete} \title{Delete a branch} \usage{ branch_delete(branch = NULL) } \arguments{ \item{branch}{The branch} } \value{ invisible NULL } \description{ Delete a branch } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "First commit message") ## Create a 'dev' branch dev <- branch_create(commit_1, name = "dev") branches(repo) ## Delete 'dev' branch branch_delete(dev) branches(repo) } } git2r/man/sub-.git_tree.Rd0000644000176200001440000000272214704742556015033 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tree.R \name{[.git_tree} \alias{[.git_tree} \title{Extract object from tree} \usage{ \method{[}{git_tree}(x, i) } \arguments{ \item{x}{The tree \code{object}} \item{i}{The index (integer or logical) of the tree object to extract. If negative values, all elements except those indicated are selected. A character vector to match against the names of objects to extract.} } \value{ Git object } \description{ Lookup a tree entry by its position in the tree } \examples{ \dontrun{ ##' Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) dir.create(file.path(path, "subfolder")) repo <- init(path) ##' Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ##' Create three files and commit writeLines("First file", file.path(path, "example-1.txt")) writeLines("Second file", file.path(path, "subfolder/example-2.txt")) writeLines("Third file", file.path(path, "example-3.txt")) add(repo, c("example-1.txt", "subfolder/example-2.txt", "example-3.txt")) new_commit <- commit(repo, "Commit message") ##' Pick a tree in the repository tree_object <- tree(new_commit) ##' Display tree tree_object ##' Select item by name tree_object["example-1.txt"] ##' Select first item in tree tree_object[1] ##' Select first three items in tree tree_object[1:3] ##' Select all blobs in tree tree_object[vapply(as(tree_object, 'list'), is_blob, logical(1))] } } git2r/man/remote_set_url.Rd0000644000176200001440000000246014704742556015413 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/remote.R \name{remote_set_url} \alias{remote_set_url} \title{Set the remote's url in the configuration} \usage{ remote_set_url(repo = ".", name = NULL, url = NULL) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{name}{The name of the remote} \item{url}{The \code{url} to set} } \value{ NULL, invisibly } \description{ This assumes the common case of a single-url remote and will otherwise raise an error. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name="Alice", user.email="alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Add a remote remote_add(repo, "playground", "https://example.org/git2r/playground") remotes(repo) remote_url(repo, "playground") ## Rename a remote remote_rename(repo, "playground", "foobar") remotes(repo) remote_url(repo, "foobar") ## Set remote url remote_set_url(repo, "foobar", "https://example.org/git2r/foobar") remotes(repo) remote_url(repo, "foobar") ## Remove a remote remote_remove(repo, "foobar") remotes(repo) } } git2r/man/sha.Rd0000644000176200001440000000265114704742556013140 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/sha.R \name{sha} \alias{sha} \alias{sha.git_blob} \alias{sha.git_branch} \alias{sha.git_commit} \alias{sha.git_note} \alias{sha.git_reference} \alias{sha.git_reflog_entry} \alias{sha.git_tag} \alias{sha.git_tree} \alias{sha.git_fetch_head} \alias{sha.git_merge_result} \title{Get the SHA-1 of a git object} \usage{ sha(object) \method{sha}{git_blob}(object) \method{sha}{git_branch}(object) \method{sha}{git_commit}(object) \method{sha}{git_note}(object) \method{sha}{git_reference}(object) \method{sha}{git_reflog_entry}(object) \method{sha}{git_tag}(object) \method{sha}{git_tree}(object) \method{sha}{git_fetch_head}(object) \method{sha}{git_merge_result}(object) } \arguments{ \item{object}{a git object to get the SHA-1 from.} } \value{ The 40 character hexadecimal string of the SHA-1. } \description{ Get the 40 character hexadecimal string of the SHA-1. } \examples{ \dontrun{ ## Create a directory in tempdir path <- tempfile(pattern="git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Commit message 1") ## Get the SHA-1 of the last commit sha(last_commit(repo)) } } git2r/man/references.Rd0000644000176200001440000000250614704742556014505 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/reference.R \name{references} \alias{references} \title{Get all references that can be found in a repository.} \usage{ references(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ Character vector with references } \description{ Get all references that can be found in a repository. } \examples{ \dontrun{ ## Initialize two temporary repositories path_bare <- tempfile(pattern="git2r-") path_repo <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo) repo_bare <- init(path_bare, bare = TRUE) repo <- clone(path_bare, path_repo) ## Config user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path_repo, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Push commits from repository to bare repository ## Adds an upstream tracking branch to branch 'master' push(repo, "origin", "refs/heads/master") ## Add tag to HEAD tag(repo, "v1.0", "First version") ## Create a note note_create(commits(repo)[[1]], "My note") ## List all references in repository references(repo) } } git2r/man/cred_ssh_key.Rd0000644000176200001440000000304714704742555015026 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/credential.R \name{cred_ssh_key} \alias{cred_ssh_key} \title{Create a new passphrase-protected ssh key credential object} \usage{ cred_ssh_key( publickey = ssh_path("id_rsa.pub"), privatekey = ssh_path("id_rsa"), passphrase = character(0) ) } \arguments{ \item{publickey}{The path to the public key of the credential. Default is \code{ssh_path("id_rsa.pub")}} \item{privatekey}{The path to the private key of the credential. Default is \code{ssh_path("id_rsa")}} \item{passphrase}{The passphrase of the credential. Default is \code{character(0)}. If getPass is installed and private key is passphrase protected \code{getPass::getPass()} will be called to allow for interactive and obfuscated interactive input of the passphrase.} } \value{ A list of class \code{cred_ssh_key} with entries: \describe{ \item{publickey}{ The path to the public key of the credential } \item{privatekey}{ The path to the private key of the credential } \item{passphrase}{ The passphrase of the credential } } } \description{ Create a new passphrase-protected ssh key credential object } \examples{ \dontrun{ ## Create a ssh key credential object. It can optionally be ## passphrase-protected cred <- cred_ssh_key(ssh_path("id_rsa.pub"), ssh_path("id_rsa")) repo <- repository("git2r") push(repo, credentials = cred) } } \seealso{ Other git credential functions: \code{\link{cred_env}()}, \code{\link{cred_token}()}, \code{\link{cred_user_pass}()} } \concept{git credential functions} git2r/man/reexports.Rd0000644000176200001440000000107614704742555014417 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/diff.R, R/merge.R, R/repository.R, R/tree.R \docType{import} \name{reexports} \alias{reexports} \alias{diff} \alias{merge} \alias{head} \alias{as.data.frame} \title{Objects exported from other packages} \keyword{internal} \description{ These objects are imported from other packages. Follow the links below to see their documentation. \describe{ \item{base}{\code{\link[base]{as.data.frame}}, \code{\link[base]{diff}}, \code{\link[base]{merge}}} \item{utils}{\code{\link[utils]{head}}} }} git2r/man/summary.git_stash.Rd0000644000176200001440000000171414704742556016045 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stash.R \name{summary.git_stash} \alias{summary.git_stash} \title{Summary of a stash} \usage{ \method{summary}{git_stash}(object, ...) } \arguments{ \item{object}{The stash \code{object}} \item{...}{Additional arguments affecting the summary produced.} } \value{ None (invisible 'NULL'). } \description{ Summary of a stash } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) # Configure a user config(repo, user.name = "Alice", user.email = "alice@example.org") # Create a file, add and commit writeLines("Hello world!", file.path(path, "test.txt")) add(repo, 'test.txt') commit(repo, "Commit message") # Change file writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) # Create stash in repository stash(repo, "Stash message") # View summary of stash summary(stash_list(repo)[[1]]) } } git2r/man/add.Rd0000644000176200001440000000416014704742555013111 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/index.R \name{add} \alias{add} \title{Add file(s) to index} \usage{ add(repo = ".", path = NULL, force = FALSE) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{path}{Character vector with file names or shell glob patterns that will matched against files in the repository's working directory. Each file that matches will be added to the index (either updating an existing entry or adding a new entry).} \item{force}{Add ignored files. Default is FALSE.} } \value{ invisible(NULL) } \description{ Add file(s) to index } \examples{ \dontrun{ ## Initialize a repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file writeLines("a", file.path(path, "a.txt")) ## Add file to repository and view status add(repo, "a.txt") status(repo) ## Add file with a leading './' when the repository working ## directory is the current working directory setwd(path) writeLines("b", file.path(path, "b.txt")) add(repo, "./b.txt") status(repo) ## Add a file in a sub-folder with sub-folder as the working ## directory. Create a file in the root of the repository ## working directory that will remain untracked. dir.create(file.path(path, "sub_dir")) setwd("./sub_dir") writeLines("c", file.path(path, "c.txt")) writeLines("c", file.path(path, "sub_dir/c.txt")) add(repo, "c.txt") status(repo) ## Add files with glob expansion when the current working ## directory is outside the repository's working directory. setwd(tempdir()) dir.create(file.path(path, "glob_dir")) writeLines("d", file.path(path, "glob_dir/d.txt")) writeLines("e", file.path(path, "glob_dir/e.txt")) writeLines("f", file.path(path, "glob_dir/f.txt")) writeLines("g", file.path(path, "glob_dir/g.md")) add(repo, "glob_dir/*txt") status(repo) ## Add file with glob expansion with a relative path when ## the current working directory is inside the repository's ## working directory. setwd(path) add(repo, "./glob_dir/*md") status(repo) } } git2r/man/length.git_diff.Rd0000644000176200001440000000053514704742555015416 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/diff.R \name{length.git_diff} \alias{length.git_diff} \title{Number of files in git_diff object} \usage{ \method{length}{git_diff}(x) } \arguments{ \item{x}{The git_diff \code{object}} } \value{ a non-negative integer } \description{ Number of files in git_diff object } git2r/man/tags.Rd0000644000176200001440000000135214704742556013320 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tag.R \name{tags} \alias{tags} \title{Tags} \usage{ tags(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ list of tags in repository } \description{ Tags } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Commit a text file writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Create tag tag(repo, "Tagname", "Tag message") ## List tags tags(repo) } } git2r/man/pull.Rd0000644000176200001440000000606114704742556013340 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/pull.R \name{pull} \alias{pull} \title{Pull} \usage{ pull(repo = ".", credentials = NULL, merger = NULL) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{credentials}{The credentials for remote repository access. Default is NULL. To use and query an ssh-agent for the ssh key credentials, let this parameter be NULL (the default).} \item{merger}{Who made the merge, if the merge is non-fast forward merge that creates a merge commit. The \code{default_signature} for \code{repo} is used if this parameter is \code{NULL}.} } \value{ A list of class \code{git_merge_result} with entries: \describe{ \item{up_to_date}{ TRUE if the merge is already up-to-date, else FALSE. } \item{fast_forward}{ TRUE if a fast-forward merge, else FALSE. } \item{conflicts}{ TRUE if the index contain entries representing file conflicts, else FALSE. } \item{sha}{ If the merge created a merge commit, the sha of the merge commit. NA if no merge commit created. } } } \description{ Pull } \examples{ \dontrun{ ## Initialize repositories path_bare <- tempfile(pattern="git2r-") path_repo_1 <- tempfile(pattern="git2r-") path_repo_2 <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo_1) dir.create(path_repo_2) repo_bare <- init(path_bare, bare = TRUE) repo_1 <- clone(path_bare, path_repo_1) ## Config first user and commit a file config(repo_1, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path_repo_1, "example.txt")) add(repo_1, "example.txt") commit(repo_1, "First commit message") ## Push commits from first repository to bare repository ## Adds an upstream tracking branch to branch 'master' push(repo_1, "origin", "refs/heads/master") ## Clone to second repository repo_2 <- clone(path_bare, path_repo_2) config(repo_2, user.name = "Bob", user.email = "bob@example.org") ## Change file and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path_repo_1, "example.txt")) add(repo_1, "example.txt") commit(repo_1, "Second commit message") ## Push commits from first repository to bare repository push(repo_1) ## Pull changes to repo_2 pull(repo_2) ## Change file again and commit. This time in repository 2 lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", "minim veniam, quis nostrud exercitation ullamco laboris nisi ut") writeLines(lines, file.path(path_repo_2, "example.txt")) add(repo_2, "example.txt") commit(repo_2, "Third commit message") ## Push commits from second repository to bare repository push(repo_2) ## Pull changes to repo_1 pull(repo_1) ## List commits in repositories commits(repo_1) commits(repo_2) commits(repo_bare) } } git2r/man/in_repository.Rd0000644000176200001440000000145114704742556015267 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{in_repository} \alias{in_repository} \title{Determine if a directory is in a git repository} \usage{ in_repository(path = ".") } \arguments{ \item{path}{The path to the directory.} } \value{ TRUE if directory is in a git repository else FALSE } \description{ The lookup start from path and walk across parent directories if nothing has been found. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Check if path is in a git repository in_repository(path) ## Check if working directory is in a git repository setwd(path) in_repository() } } git2r/man/is_branch.Rd0000644000176200001440000000146314704742555014314 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/branch.R \name{is_branch} \alias{is_branch} \title{Check if object is \code{git_branch}} \usage{ is_branch(object) } \arguments{ \item{object}{Check if object is of class \code{git_branch}} } \value{ TRUE if object is class \code{git_branch}, else FALSE } \description{ Check if object is \code{git_branch} } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Commit a text file writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") branch <- branches(repo)[[1]] ## Check if branch is_branch(branch) } } git2r/man/remotes.Rd0000644000176200001440000000222314704742556014036 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/remote.R \name{remotes} \alias{remotes} \title{Get the configured remotes for a repo} \usage{ remotes(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ Character vector with remotes } \description{ Get the configured remotes for a repo } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name="Alice", user.email="alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Add a remote remote_add(repo, "playground", "https://example.org/git2r/playground") remotes(repo) remote_url(repo, "playground") ## Rename a remote remote_rename(repo, "playground", "foobar") remotes(repo) remote_url(repo, "foobar") ## Set remote url remote_set_url(repo, "foobar", "https://example.org/git2r/foobar") remotes(repo) remote_url(repo, "foobar") ## Remove a remote remote_remove(repo, "foobar") remotes(repo) } } git2r/man/cred_token.Rd0000644000176200001440000000265114704742555014501 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/credential.R \name{cred_token} \alias{cred_token} \title{Create a new personal access token credential object} \usage{ cred_token(token = "GITHUB_PAT") } \arguments{ \item{token}{The name of the environmental variable that holds the personal access token for the authentication. Default is \code{GITHUB_PAT}.} } \value{ A list of class \code{cred_token} with entry: \describe{ \item{token}{ The name of the environmental variable that holds the personal access token for the authentication. } } } \description{ The personal access token is stored in an envrionmental variable. Environmental variables can be written to the file \code{.Renviron}. This file is read by \emph{R} during startup, see \code{\link[base]{Startup}}. On GitHub, personal access tokens function like ordinary OAuth access tokens. They can be used instead of a password for Git over HTTPS, see the \dQuote{Creating a personal access token} article on GitHub Docs. } \examples{ \dontrun{ ## Create a personal access token credential object. ## This example assumes that the token is stored in ## the 'GITHUB_PAT' environmental variable. repo <- repository("git2r") cred <- cred_token() push(repo, credentials = cred) } } \seealso{ Other git credential functions: \code{\link{cred_env}()}, \code{\link{cred_ssh_key}()}, \code{\link{cred_user_pass}()} } \concept{git credential functions} git2r/man/merge_base.Rd0000644000176200001440000000254714704742555014461 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/merge.R \name{merge_base} \alias{merge_base} \title{Find a merge base between two commits} \usage{ merge_base(one = NULL, two = NULL) } \arguments{ \item{one}{One of the commits} \item{two}{The other commit} } \value{ git_commit } \description{ Find a merge base between two commits } \examples{ \dontrun{ ## Create a directory in tempdir path <- tempfile(pattern="git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit writeLines("Master branch", file.path(path, "master_branch.txt")) add(repo, "master_branch.txt") commit_1 <- commit(repo, "Commit message 1") ## Create first branch, checkout, add file and commit branch_1 <- branch_create(commit_1, "branch_1") checkout(branch_1) writeLines("Branch 1", file.path(path, "branch_1.txt")) add(repo, "branch_1.txt") commit_2 <- commit(repo, "Commit message branch_1") ## Create second branch, checkout, add file and commit branch_2 <- branch_create(commit_1, "branch_2") checkout(branch_2) writeLines("Branch 2", file.path(path, "branch_2.txt")) add(repo, "branch_2.txt") commit_3 <- commit(repo, "Commit message branch_2") ## Check that merge base equals commit_1 stopifnot(identical(merge_base(commit_2, commit_3), commit_1)) } } git2r/man/punch_card.Rd0000644000176200001440000000133114704742556014465 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/punch_card.R \name{punch_card} \alias{punch_card} \title{Punch card} \usage{ punch_card(repo = ".", main = NULL, ...) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{main}{Default title for the plot is "Punch card on repo:" and repository workdir basename. Supply a new title if you desire one.} \item{...}{Additional arguments affecting the plot} } \value{ invisible NULL } \description{ Punch card } \examples{ \dontrun{ ## Initialize repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- clone("https://github.com/ropensci/git2r.git", path) ## Plot punch_card(repo) } } git2r/man/libgit2_features.Rd0000644000176200001440000000056414704742555015617 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/libgit2.R \name{libgit2_features} \alias{libgit2_features} \title{Compile time options for libgit2.} \usage{ libgit2_features() } \value{ A list with threads, https and ssh set to TRUE/FALSE. } \description{ Compile time options for libgit2. } \examples{ libgit2_features() } \keyword{methods} git2r/man/clone.Rd0000644000176200001440000000457114704742556013470 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{clone} \alias{clone} \title{Clone a remote repository} \usage{ clone( url = NULL, local_path = NULL, bare = FALSE, branch = NULL, checkout = TRUE, credentials = NULL, progress = TRUE ) } \arguments{ \item{url}{The remote repository to clone} \item{local_path}{Local directory to clone to.} \item{bare}{Create a bare repository. Default is FALSE.} \item{branch}{The name of the branch to checkout. Default is NULL which means to use the remote's default branch.} \item{checkout}{Checkout HEAD after the clone is complete. Default is TRUE.} \item{credentials}{The credentials for remote repository access. Default is NULL. To use and query an ssh-agent for the ssh key credentials, let this parameter be NULL (the default).} \item{progress}{Show progress. Default is TRUE.} } \value{ A \code{git_repository} object. } \description{ Clone a remote repository } \examples{ \dontrun{ ## Initialize repository path_repo_1 <- tempfile(pattern="git2r-") path_repo_2 <- tempfile(pattern="git2r-") dir.create(path_repo_1) dir.create(path_repo_2) repo_1 <- init(path_repo_1) ## Config user and commit a file config(repo_1, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit writeLines( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", file.path(path_repo_1, "example.txt")) add(repo_1, "example.txt") commit(repo_1, "First commit message") ## Change file and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path_repo_1, "example.txt")) add(repo_1, "example.txt") commit(repo_1, "Second commit message") ## Change file again and commit. lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", "minim veniam, quis nostrud exercitation ullamco laboris nisi ut") writeLines(lines, file.path(path_repo_1, "example.txt")) add(repo_1, "example.txt") commit(repo_1, "Third commit message") ## Clone to second repository repo_2 <- clone(path_repo_1, path_repo_2) ## List commits in repositories commits(repo_1) commits(repo_2) } } \seealso{ \link{repository}, \code{\link{cred_user_pass}}, \code{\link{cred_ssh_key}} } git2r/man/notes.Rd0000644000176200001440000000301414704742555013506 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/note.R \name{notes} \alias{notes} \title{List notes} \usage{ notes(repo = ".", ref = NULL) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{ref}{Reference to read from. Default (ref = NULL) is to call \code{note_default_ref}.} } \value{ list with git_note objects } \description{ List all the notes within a specified namespace. } \examples{ \dontrun{ ## Create and initialize a repository in a temporary directory path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "Commit message 1") ## Create another commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "example.txt")) add(repo, "example.txt") commit_2 <- commit(repo, "Commit message 2") ## Create note in default namespace note_create(commit_1, "Note-1") note_create(commit_1, "Note-2", force = TRUE) ## Create note in named (review) namespace note_create(commit_1, "Note-3", ref="refs/notes/review") note_create(commit_2, "Note-4", ref="review") ## Create note on blob and tree note_create(tree(commit_1), "Note-5") note_create(tree(commit_1)["example.txt"], "Note-6") ## List notes in default namespace notes(repo) ## List notes in 'review' namespace notes(repo, "review") } } git2r/man/blame.Rd0000644000176200001440000000433614704742555013446 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/blame.R \name{blame} \alias{blame} \title{Get blame for file} \usage{ blame(repo = ".", path = NULL) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{path}{Path to the file to consider} } \value{ git_blame object with the following entries: \describe{ \item{path}{ The path to the file of the blame } \item{hunks}{ List of blame hunks } \item{repo}{ The git_repository that contains the file } } \describe{ \item{lines_in_hunk}{ The number of lines in this hunk } \item{final_commit_id}{ The sha of the commit where this line was last changed } \item{final_start_line_number}{ The 1-based line number where this hunk begins, in the final version of the file } \item{final_signature}{ Final committer } \item{orig_commit_id}{ The sha of the commit where this hunk was found. This will usually be the same as 'final_commit_id'. } \item{orig_start_line_number}{ The 1-based line number where this hunk begins in the file named by 'orig_path' in the commit specified by 'orig_commit_id'. } \item{orig_signature}{ Origin committer } \item{orig_path}{ The path to the file where this hunk originated, as of the commit specified by 'orig_commit_id' } \item{boundary}{ TRUE iff the hunk has been tracked to a boundary commit. } \item{repo}{ The \code{git_repository} object that contains the blame hunk } } } \description{ Get blame for file } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a first user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Create a second user and change the file config(repo, user.name = "Bob", user.email = "bob@example.org") writeLines(c("Hello world!", "HELLO WORLD!", "HOLA"), file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "Second commit message") ## Check blame blame(repo, "example.txt") } } git2r/man/print.git_reflog_entry.Rd0000644000176200001440000000137414704742556017063 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/reflog.R \name{print.git_reflog_entry} \alias{print.git_reflog_entry} \title{Print a reflog entry} \usage{ \method{print}{git_reflog_entry}(x, ...) } \arguments{ \item{x}{The reflog entry} \item{...}{Unused} } \value{ None (invisible 'NULL'). } \description{ Print a reflog entry } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## View repository HEAD reflog reflog(repo) } } git2r/man/ssl_cert_locations.Rd0000644000176200001440000000116214704742555016251 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/libgit2.R \name{ssl_cert_locations} \alias{ssl_cert_locations} \title{Set the SSL certificate-authority locations} \usage{ ssl_cert_locations(filename = NULL, path = NULL) } \arguments{ \item{filename}{Location of a file containing several certificates concatenated together. Default NULL.} \item{path}{Location of a directory holding several certificates, one per file. Default NULL.} } \value{ invisible(NULL) } \description{ Set the SSL certificate-authority locations } \note{ Either parameter may be 'NULL', but not both. } \keyword{methods} git2r/man/git_time.Rd0000644000176200001440000000432414704742556014165 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/time.R \name{git_time} \alias{git_time} \alias{as.character.git_time} \alias{format.git_time} \alias{as.POSIXct.git_time} \alias{print.git_time} \title{Time} \usage{ \method{as.character}{git_time}(x, tz = "GMT", origin = "1970-01-01", usetz = TRUE, ...) \method{format}{git_time}(x, tz = "GMT", origin = "1970-01-01", usetz = TRUE, ...) \method{as.POSIXct}{git_time}(x, tz = "GMT", origin = "1970-01-01", ...) \method{print}{git_time}(x, tz = "GMT", origin = "1970-01-01", usetz = TRUE, ...) } \arguments{ \item{x}{\R object to be converted.} \item{tz}{a character string. The time zone specification to be used for the conversion, \emph{if one is required}. System-specific (see \link[base]{time zones}), but \code{""} is the current time zone, and \code{"GMT"} is UTC (Universal Time, Coordinated). Invalid values are most commonly treated as UTC, on some platforms with a warning.} \item{origin}{a date-time object, or something which can be coerced by \code{as.POSIXct(tz = "GMT")} to such an object. Optional since \R 4.3.0, where the equivalent of \code{"1970-01-01"} is used.} \item{usetz}{logical. Should the time zone abbreviation be appended to the output? This is used in printing times, and more reliable than using \code{"\%Z"}.} \item{...}{further arguments to be passed to or from other methods.} } \description{ The class \code{git_time} stores the time a Git object was created. } \details{ The default is to use \code{tz = "GMT"} and \code{origin = "1970-01-01"}. To use your local timezone, set \code{tz = Sys.timezone()}. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a first user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Create tag tag(repo, "Tagname", "Tag message") as.POSIXct(commits(repo)[[1]]$author$when) as.POSIXct(tags(repo)[[1]]$tagger$when) as.POSIXct(tags(repo)[[1]]$tagger$when, tz = Sys.timezone()) } } \seealso{ \code{\link{when}} } git2r/man/branch_remote_name.Rd0000644000176200001440000000223514704742555016172 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/branch.R \name{branch_remote_name} \alias{branch_remote_name} \title{Remote name of a branch} \usage{ branch_remote_name(branch = NULL) } \arguments{ \item{branch}{The branch} } \value{ character string with remote name } \description{ The name of remote that the remote tracking branch belongs to } \examples{ \dontrun{ ## Initialize two temporary repositories path_bare <- tempfile(pattern="git2r-") path_repo <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo) repo_bare <- init(path_bare, bare = TRUE) repo <- clone(path_bare, path_repo) ## Config user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path_repo, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Push commits from repository to bare repository ## Adds an upstream tracking branch to branch 'master' push(repo, "origin", "refs/heads/master") ## Get remote name branch_remote_name(branches(repo)[[2]]) } } git2r/man/last_commit.Rd0000644000176200001440000000171714704742555014701 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/commit.R \name{last_commit} \alias{last_commit} \title{Last commit} \usage{ last_commit(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \description{ Get last commit in the current branch. } \examples{ \dontrun{ ## Initialize a repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Config user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Get last commit last_commit(repo) last_commit(path) ## Coerce the last commit to a data.frame as.data.frame(last_commit(path), "data.frame") ## Summary of last commit in repository summary(last_commit(repo)) } } git2r/man/as.data.frame.git_tree.Rd0000644000176200001440000000270214704742556016567 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tree.R \name{as.data.frame.git_tree} \alias{as.data.frame.git_tree} \title{Coerce entries in a git_tree to a \code{data.frame}} \usage{ \method{as.data.frame}{git_tree}(x, ...) } \arguments{ \item{x}{The tree \code{object}} \item{...}{Additional arguments. Not used.} } \value{ \code{data.frame} } \description{ The entries in a tree are coerced to a \code{data.frame} } \details{ The \code{data.frame} have the following columns: \describe{ \item{filemode}{ The UNIX file attributes of a tree entry } \item{type}{ String representation of the tree entry type } \item{sha}{ The sha of a tree entry } \item{name}{ The filename of a tree entry } } } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) dir.create(file.path(path, "subfolder")) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create three files and commit writeLines("First file", file.path(path, "example-1.txt")) writeLines("Second file", file.path(path, "subfolder/example-2.txt")) writeLines("Third file", file.path(path, "example-3.txt")) add(repo, c("example-1.txt", "subfolder/example-2.txt", "example-3.txt")) commit(repo, "Commit message") ## Display tree tree(last_commit(repo)) ## Coerce tree to a data.frame df <- as.data.frame(tree(last_commit(repo))) df } } git2r/man/discover_repository.Rd0000644000176200001440000000353614704742556016505 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{discover_repository} \alias{discover_repository} \title{Find path to repository for any file} \usage{ discover_repository(path = ".", ceiling = NULL) } \arguments{ \item{path}{A character vector specifying the path to a file or folder} \item{ceiling}{The default is to not use the ceiling argument and start the lookup from path and walk across parent directories. When ceiling is 0, the lookup is only in path. When ceiling is 1, the lookup is in both the path and the parent to path.} } \value{ Character vector with path (terminated by a file separator) to repository or NULL if this cannot be established. } \description{ Find path to repository for any file } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "example-1.txt")) add(repo, "example-1.txt") commit(repo, "First commit message") ## Create a second file. The file is not added for version control ## in the repository. dir.create(file.path(path, "example")) file_2 <- file.path(path, "example/example-2.txt") writeLines("Not under version control", file_2) ## Find the path to the repository using the path to the second file discover_repository(file_2) ## Demonstrate the 'ceiling' argument wd <- workdir(repo) dir.create(file.path(wd, "temp")) ## Lookup repository in 'file.path(wd, "temp")'. Should return NULL discover_repository(file.path(wd, "temp"), ceiling = 0) ## Lookup repository in parent to 'file.path(wd, "temp")'. ## Should not return NULL discover_repository(file.path(wd, "temp"), ceiling = 1) } } git2r/man/is_bare.Rd0000644000176200001440000000130514704742556013764 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{is_bare} \alias{is_bare} \title{Check if repository is bare} \usage{ is_bare(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ \code{TRUE} if bare repository, else \code{FALSE} } \description{ Check if repository is bare } \examples{ \dontrun{ ## Initialize a repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) is_bare(repo) ## Initialize a bare repository path_bare <- tempfile(pattern="git2r-") dir.create(path_bare) repo_bare <- init(path_bare, bare = TRUE) is_bare(repo_bare) } } \seealso{ \link{init} } git2r/man/commits.Rd0000644000176200001440000000657514704742555014050 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/commit.R \name{commits} \alias{commits} \title{Commits} \usage{ commits( repo = ".", topological = TRUE, time = TRUE, reverse = FALSE, n = NULL, ref = NULL, path = NULL ) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{topological}{Sort the commits in topological order (parents before children); can be combined with time sorting. Default is TRUE.} \item{time}{Sort the commits by commit time; Can be combined with topological sorting. Default is TRUE.} \item{reverse}{Sort the commits in reverse order; can be combined with topological and/or time sorting. Default is FALSE.} \item{n}{The upper limit of the number of commits to output. The default is NULL for unlimited number of commits.} \item{ref}{The name of a reference to list commits from e.g. a tag or a branch. The default is NULL for the current branch.} \item{path}{The path to a file. If not NULL, only commits modifying this file will be returned. Note that modifying commits that occurred before the file was given its present name are not returned; that is, the output of \code{git log} with \code{--no-follow} is reproduced.} } \value{ list of commits in repository } \description{ Commits } \examples{ \dontrun{ ## Initialize a repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Config user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Change file and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "Second commit message") ## Create a tag tag(repo, "Tagname", "Tag message") ## Change file again and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad", "minim veniam, quis nostrud exercitation ullamco laboris nisi ut") writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "Third commit message") ## Create a new file containing R code, and commit. writeLines(c("x <- seq(1,100)", "print(mean(x))"), file.path(path, "mean.R")) add(repo, "mean.R") commit(repo, "Fourth commit message") ## List the commits in the repository commits(repo) ## List the commits starting from the tag commits(repo, ref = "Tagname") ## List the commits modifying example.txt and mean.R. commits(repo, path = "example.txt") commits(repo, path = "mean.R") ## Create and checkout 'dev' branch in the repo checkout(repo, "dev", create = TRUE) ## Add changes to the 'dev' branch lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "Commit message in dev branch") ## Checkout the 'master' branch again and list the commits ## starting from the 'dev' branch. checkout(repo, "master") commits(repo, ref = "dev") } } git2r/man/revparse_single.Rd0000644000176200001440000000246514704742556015560 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/revparse.R \name{revparse_single} \alias{revparse_single} \title{Revparse} \usage{ revparse_single(repo = ".", revision = NULL) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{revision}{The revision string, see http://git-scm.com/docs/git-rev-parse.html#_specifying_revisions} } \value{ a \code{git_commit} or \code{git_tag} or \code{git_tree} object } \description{ Find object specified by revision. } \examples{ \dontrun{ ## Create a directory in tempdir path <- tempfile(pattern="git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "First commit message") # Change file and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Second commit message") revparse_single(repo, "HEAD^") revparse_single(repo, "HEAD:test.txt") } } git2r/man/is_detached.Rd0000644000176200001440000000250014704742556014612 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{is_detached} \alias{is_detached} \title{Check if HEAD of repository is detached} \usage{ is_detached(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ \code{TRUE} if repository HEAD is detached, else \code{FALSE}. } \description{ Check if HEAD of repository is detached } \examples{ \dontrun{ ## Create and initialize a repository in a temporary directory path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "Commit message 1") ## Change file, add and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "Commit message 2") ## HEAD of repository is not detached is_detached(repo) ## Checkout first commit checkout(commit_1) ## HEAD of repository is detached is_detached(repo) } } git2r/man/plot.git_repository.Rd0000644000176200001440000000152514704742556016423 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/plot.R \name{plot.git_repository} \alias{plot.git_repository} \title{Plot commits over time} \usage{ \method{plot}{git_repository}( x, breaks = c("month", "year", "quarter", "week", "day"), main = NULL, ... ) } \arguments{ \item{x}{The repository to plot} \item{breaks}{Default is \code{month}. Change to year, quarter, week or day as necessary.} \item{main}{Default title for the plot is "Commits on repo:" and repository workdir basename. Supply a new title if you desire one.} \item{...}{Additional arguments affecting the plot} } \description{ Plot commits over time } \examples{ \dontrun{ ## Initialize repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- clone("https://github.com/ropensci/git2r.git", path) ## Plot commits plot(repo) } } git2r/man/blob_create.Rd0000644000176200001440000000323314704742555014622 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/blob.R \name{blob_create} \alias{blob_create} \title{Create blob from file on disk} \usage{ blob_create(repo = ".", path = NULL, relative = TRUE) } \arguments{ \item{repo}{The repository where the blob(s) will be written. Can be a bare repository. A \code{git_repository} object, or a path to a repository, or \code{NULL}. If the \code{repo} argument is \code{NULL}, the repository is searched for with \code{\link{discover_repository}} in the current working directory.} \item{path}{The file(s) from which the blob will be created.} \item{relative}{TRUE if the file(s) from which the blob will be created is relative to the repository's working dir. Default is TRUE.} } \value{ list of S3 class git_blob \code{objects} } \description{ Read a file from the filesystem and write its content to the Object Database as a loose blob. The method is vectorized and accepts a vector of files to create blobs from. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create blobs from files relative to workdir writeLines("Hello, world!", file.path(path, "example-1.txt")) writeLines("test content", file.path(path, "example-2.txt")) blob_list_1 <- blob_create(repo, c("example-1.txt", "example-2.txt")) ## Create blobs from files not relative to workdir temp_file_1 <- tempfile() temp_file_2 <- tempfile() writeLines("Hello, world!", temp_file_1) writeLines("test content", temp_file_2) blob_list_2 <- blob_create(repo, c(temp_file_1, temp_file_2), relative = FALSE) } } git2r/man/is_empty.Rd0000644000176200001440000000154114704742556014213 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{is_empty} \alias{is_empty} \title{Check if repository is empty} \usage{ is_empty(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ \code{TRUE} if repository is empty else \code{FALSE}. } \description{ Check if repository is empty } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Check if it's an empty repository is_empty(repo) ## Commit a file writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Check if it's an empty repository is_empty(repo) } } git2r/man/stash_apply.Rd0000644000176200001440000000356514704742556014721 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stash.R \name{stash_apply} \alias{stash_apply} \title{Apply stash} \usage{ stash_apply(object = ".", index = 1) } \arguments{ \item{object}{path to a repository, or a \code{git_repository} object, or the stash \code{object} to pop. Default is a \code{path = '.'} to a reposiory.} \item{index}{The index to the stash to apply. Only used when \code{object} is a path to a repository or a \code{git_repository} object. Default is \code{index = 1}.} } \value{ invisible NULL } \description{ Apply a single stashed state from the stash list. } \details{ If local changes in the working directory conflict with changes in the stash then an error will be raised. In this case, the index will always remain unmodified and all files in the working directory will remain unmodified. However, if you are restoring untracked files or ignored files and there is a conflict when applying the modified files, then those files will remain in the working directory. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) # Configure a user config(repo, user.name = "Alice", user.email = "alice@example.org") # Create a file, add and commit writeLines("Hello world!", file.path(path, "test.txt")) add(repo, 'test.txt') commit(repo, "Commit message") # Change file writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) # Create stash in repository stash(repo) # Change file writeLines(c("Hello world!", "HeLlO wOrLd!"), file.path(path, "test.txt")) # Create stash in repository stash(repo) # View stashes stash_list(repo) # Read file readLines(file.path(path, "test.txt")) # Apply latest git_stash object in repository stash_apply(stash_list(repo)[[1]]) # Read file readLines(file.path(path, "test.txt")) # View stashes stash_list(repo) } } git2r/man/merge.Rd0000644000176200001440000000752314704742555013466 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/merge.R \name{merge.git_branch} \alias{merge.git_branch} \alias{merge.git_repository} \alias{merge.character} \title{Merge a branch into HEAD} \usage{ \method{merge}{git_branch}(x, y = NULL, commit_on_success = TRUE, merger = NULL, fail = FALSE, ...) \method{merge}{git_repository}(x, y = NULL, commit_on_success = TRUE, merger = NULL, fail = FALSE, ...) \method{merge}{character}( x = ".", y = NULL, commit_on_success = TRUE, merger = NULL, fail = FALSE, ... ) } \arguments{ \item{x}{A path (default '.') to a repository, or a \code{git_repository} object, or a \code{git_branch}.} \item{y}{If \code{x} is a \code{git_repository}, the name of the branch to merge into HEAD. Not used if \code{x} is a \code{git_branch}.} \item{commit_on_success}{If there are no conflicts written to the index, the merge commit will be committed. Default is TRUE.} \item{merger}{Who made the merge. The default (\code{NULL}) is to use \code{default_signature} for the repository.} \item{fail}{If a conflict occurs, exit immediately instead of attempting to continue resolving conflicts. Default is \code{FALSE}.} \item{...}{Additional arguments (unused).} } \value{ A list of class \code{git_merge_result} with entries: \describe{ \item{up_to_date}{ TRUE if the merge is already up-to-date, else FALSE. } \item{fast_forward}{ TRUE if a fast-forward merge, else FALSE. } \item{conflicts}{ TRUE if the index contain entries representing file conflicts, else FALSE. } \item{sha}{ If the merge created a merge commit, the sha of the merge commit. NA if no merge commit created. } } } \description{ Merge a branch into HEAD } \examples{ \dontrun{ ## Create a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) config(repo, user.name="Alice", user.email = "alice@example.org") ## Create a file, add and commit writeLines("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", con = file.path(path, "test.txt")) add(repo, "test.txt") commit_1 <- commit(repo, "Commit message 1") ## Create first branch, checkout, add file and commit checkout(repo, "branch1", create = TRUE) writeLines("Branch 1", file.path(path, "branch-1.txt")) add(repo, "branch-1.txt") commit(repo, "Commit message branch 1") ## Create second branch, checkout, add file and commit b_2 <- branch_create(commit_1, "branch2") checkout(b_2) writeLines("Branch 2", file.path(path, "branch-2.txt")) add(repo, "branch-2.txt") commit(repo, "Commit message branch 2") ## Make a change to 'test.txt' writeLines(c("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Second commit message branch 2") ## Checkout master checkout(repo, "master", force = TRUE) ## Merge branch 1 merge(repo, "branch1") ## Merge branch 2 merge(repo, "branch2") ## Create third branch, checkout, change file and commit checkout(repo, "branch3", create=TRUE) writeLines(c("Lorem ipsum dolor amet sit, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Commit message branch 3") ## Checkout master and create a change that creates a merge conflict checkout(repo, "master", force=TRUE) writeLines(c("Lorem ipsum dolor sit amet, adipisicing consectetur elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua."), con = file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Some commit message branch 1") ## Merge branch 3 merge(repo, "branch3") ## Check status; Expect to have one unstaged unmerged conflict. status(repo) } } git2r/man/descendant_of.Rd0000644000176200001440000000315414704742555015157 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/commit.R \name{descendant_of} \alias{descendant_of} \title{Descendant} \usage{ descendant_of(commit = NULL, ancestor = NULL) } \arguments{ \item{commit}{a git_commit object. Can also be a tag or a branch, and in that case the commit will be the target of the tag or branch.} \item{ancestor}{a git_commit object to check if ancestor to \code{commit}. Can also be a tag or a branch, and in that case the commit will be the target of the tag or branch.} } \value{ TRUE if \code{commit} is descendant of \code{ancestor}, else FALSE } \description{ Determine if a commit is the descendant of another commit } \examples{ \dontrun{ ## Create a directory in tempdir path <- tempfile(pattern="git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "test.txt")) add(repo, "test.txt") commit_1 <- commit(repo, "Commit message 1") tag_1 <- tag(repo, "Tagname1", "Tag message 1") # Change file and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path, "test.txt")) add(repo, "test.txt") commit_2 <- commit(repo, "Commit message 2") tag_2 <- tag(repo, "Tagname2", "Tag message 2") descendant_of(commit_1, commit_2) descendant_of(commit_2, commit_1) descendant_of(tag_1, tag_2) descendant_of(tag_2, tag_1) } } git2r/man/tag.Rd0000644000176200001440000000274414704742556013143 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tag.R \name{tag} \alias{tag} \title{Create tag targeting HEAD commit in repository} \usage{ tag( object = ".", name = NULL, message = NULL, session = FALSE, tagger = NULL, force = FALSE ) } \arguments{ \item{object}{The repository \code{object}.} \item{name}{Name for the tag.} \item{message}{The tag message. Specify a tag message to create an annotated tag. A lightweight tag is created if the message parameter is \code{NULL}.} \item{session}{Add sessionInfo to tag message. Default is FALSE.} \item{tagger}{The tagger (author) of the tag} \item{force}{Overwrite existing tag. Default = FALSE} } \value{ invisible(\code{git_tag}) object } \description{ Create tag targeting HEAD commit in repository } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Commit a text file filename <- file.path(path, "example.txt") writeLines("Hello world!", filename) add(repo, "example.txt") commit(repo, "First commit message") ## Create an annotated tag tag(repo, "v1.0", "Tag message") ## List tags tags(repo) ## Make a change to the text file and commit. writeLines(c("Hello world!", "HELLO WORLD!"), filename) add(repo, "example.txt") commit(repo, "Second commit message") ## Create a lightweight tag tag(repo, "v2.0") ## List tags tags(repo) } } git2r/man/branch_remote_url.Rd0000644000176200001440000000225414704742555016055 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/branch.R \name{branch_remote_url} \alias{branch_remote_url} \title{Remote url of a branch} \usage{ branch_remote_url(branch = NULL) } \arguments{ \item{branch}{The branch} } \value{ character string with remote url } \description{ Remote url of a branch } \examples{ \dontrun{ ## Initialize two temporary repositories path_bare <- tempfile(pattern="git2r-") path_repo <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo) repo_bare <- init(path_bare, bare = TRUE) repo <- clone(path_bare, path_repo) ## Config user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") ## Write to a file and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path_repo, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Push commits from repository to bare repository ## Adds an upstream tracking branch to branch 'master' push(repo, "origin", "refs/heads/master") ## Get remote url of tracking branch to branch 'master' branch_remote_url(branch_get_upstream(repository_head(repo))) } } git2r/man/stash.Rd0000644000176200001440000000302714704742556013505 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stash.R \name{stash} \alias{stash} \title{Stash} \usage{ stash( repo = ".", message = as.character(Sys.time()), index = FALSE, untracked = FALSE, ignored = FALSE, stasher = NULL ) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{message}{Optional description. Defaults to current time.} \item{index}{All changes already added to the index are left intact in the working directory. Default is FALSE} \item{untracked}{All untracked files are also stashed and then cleaned up from the working directory. Default is FALSE} \item{ignored}{All ignored files are also stashed and then cleaned up from the working directory. Default is FALSE} \item{stasher}{Signature with stasher and time of stash} } \value{ invisible \code{git_stash} object if anything to stash else NULL } \description{ Stash } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) # Configure a user config(repo, user.name = "Alice", user.email = "alice@example.org") # Create a file, add and commit writeLines("Hello world!", file.path(path, "test.txt")) add(repo, 'test.txt') commit(repo, "Commit message") # Change file writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt")) # Check status of repository status(repo) # Create stash in repository stash(repo) # Check status of repository status(repo) # View stash stash_list(repo) } } git2r/man/init.Rd0000644000176200001440000000200414704742556013320 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{init} \alias{init} \title{Init a repository} \usage{ init(path = ".", bare = FALSE, branch = NULL) } \arguments{ \item{path}{A path to where to init a git repository} \item{bare}{If TRUE, a Git repository without a working directory is created at the pointed path. If FALSE, provided path will be considered as the working directory into which the .git directory will be created.} \item{branch}{Use the specified name for the initial branch in the newly created repository. If \code{branch=NULL}, fall back to the default name.} } \value{ A \code{git_repository} object } \description{ Init a repository } \examples{ \dontrun{ ## Initialize a repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) is_bare(repo) ## Initialize a bare repository path_bare <- tempfile(pattern="git2r-") dir.create(path_bare) repo_bare <- init(path_bare, bare = TRUE) is_bare(repo_bare) } } \seealso{ \link{repository} } git2r/man/length.git_tree.Rd0000644000176200001440000000055614704742556015451 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tree.R \name{length.git_tree} \alias{length.git_tree} \title{Number of entries in tree} \usage{ \method{length}{git_tree}(x) } \arguments{ \item{x}{The tree \code{object}} } \value{ a non-negative integer or double (which will be rounded down) } \description{ Number of entries in tree } git2r/man/hash.Rd0000644000176200001440000000111214704742555013276 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/blob.R \name{hash} \alias{hash} \title{Determine the sha from a blob string} \usage{ hash(data = NULL) } \arguments{ \item{data}{The string vector to hash.} } \value{ A string vector with the sha for each string in data. } \description{ The blob is not written to the object database. } \examples{ \dontrun{ identical(hash(c("Hello, world!\n", "test content\n")), c("af5626b4a114abcb82d63db7c8082c3c4756e51b", "d670460b4b4aece5915caf5c68d12f560a9fe3e4")) } } git2r/man/head.git_repository.Rd0000644000176200001440000000162514704742556016347 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{head.git_repository} \alias{head.git_repository} \title{Get HEAD for a repository} \usage{ \method{head}{git_repository}(x, ...) } \arguments{ \item{x}{The repository \code{x} to check head} \item{...}{Additional arguments. Unused.} } \value{ NULL if unborn branch or not found. A git_branch if not a detached head. A git_commit if detached head } \description{ Get HEAD for a repository } \examples{ \dontrun{ ## Create and initialize a repository in a temporary directory path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "Commit message") ## Get HEAD of repository repository_head(repo) } } git2r/man/is_commit.Rd0000644000176200001440000000142414704742555014344 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/commit.R \name{is_commit} \alias{is_commit} \title{Check if object is a git_commit object} \usage{ is_commit(object) } \arguments{ \item{object}{Check if object is a git_commit object} } \value{ TRUE if object is a git_commit, else FALSE } \description{ Check if object is a git_commit object } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Commit a text file writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "First commit message") ## Check if commit is_commit(commit_1) } } git2r/man/is_binary.Rd0000644000176200001440000000177214704742555014346 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/blob.R \name{is_binary} \alias{is_binary} \title{Is blob binary} \usage{ is_binary(blob = NULL) } \arguments{ \item{blob}{The blob \code{object}.} } \value{ TRUE if binary data, FALSE if not. } \description{ Is blob binary } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Commit a text file writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "First commit message") ## Check if binary b_text <- tree(commit_1)["example.txt"] is_binary(b_text) ## Commit plot file (binary) x <- 1:100 y <- x^2 png(file.path(path, "plot.png")) plot(y ~ x, type = "l") dev.off() add(repo, "plot.png") commit_2 <- commit(repo, "Second commit message") ## Check if binary b_png <- tree(commit_2)["plot.png"] is_binary(b_png) } } git2r/man/is_blob.Rd0000644000176200001440000000147714704742555014002 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/blob.R \name{is_blob} \alias{is_blob} \title{Check if object is S3 class git_blob} \usage{ is_blob(object) } \arguments{ \item{object}{Check if object is S3 class git_blob} } \value{ TRUE if object is S3 class git_blob, else FALSE } \description{ Check if object is S3 class git_blob } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Commit a text file writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "First commit message") blob_1 <- tree(commit_1)["example.txt"] ## Check if blob is_blob(commit_1) is_blob(blob_1) } } git2r/man/stash_list.Rd0000644000176200001440000000232514704742556014540 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stash.R \name{stash_list} \alias{stash_list} \title{List stashes in repository} \usage{ stash_list(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ list of stashes in repository } \description{ List stashes in repository } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) # Configure a user config(repo, user.name = "Alice", user.email = "alice@example.org") # Create a file, add and commit writeLines("Hello world!", file.path(path, "test-1.txt")) add(repo, 'test-1.txt') commit(repo, "Commit message") # Make one more commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test-1.txt")) add(repo, 'test-1.txt') commit(repo, "Next commit message") # Create one more file writeLines("Hello world!", file.path(path, "test-2.txt")) # Check that there are no stashes stash_list(repo) # Stash stash(repo) # Only untracked changes, therefore no stashes stash_list(repo) # Stash and include untracked changes stash(repo, "Stash message", untracked=TRUE) # View stash stash_list(repo) } } git2r/man/lookup_commit.Rd0000644000176200001440000000254214704742556015245 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{lookup_commit} \alias{lookup_commit} \alias{lookup_commit.git_branch} \alias{lookup_commit.git_commit} \alias{lookup_commit.git_tag} \alias{lookup_commit.git_reference} \title{Lookup the commit related to a git object} \usage{ lookup_commit(object) \method{lookup_commit}{git_branch}(object) \method{lookup_commit}{git_commit}(object) \method{lookup_commit}{git_tag}(object) \method{lookup_commit}{git_reference}(object) } \arguments{ \item{object}{a git object to get the related commit from.} } \value{ A git commit object. } \description{ Lookup the commit related to a git_reference, git_tag or git_branch object. } \examples{ \dontrun{ ## Create a directory in tempdir path <- tempfile(pattern="git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, con = file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Commit message 1") ## Get the commit pointed to by the 'master' branch lookup_commit(repository_head(repo)) ## Create a tag a_tag <- tag(repo, "Tagname", "Tag message") ## Get the commit pointed to by 'a_tag' lookup_commit(a_tag) } } git2r/man/libgit2_version.Rd0000644000176200001440000000057614704742555015471 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/libgit2.R \name{libgit2_version} \alias{libgit2_version} \title{Version of the libgit2 library} \usage{ libgit2_version() } \value{ A list with major, minor and rev } \description{ Version of the libgit2 library that the bundled source code is based on } \examples{ libgit2_version() } \keyword{methods} git2r/man/remote_rename.Rd0000644000176200001440000000233314704742556015204 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/remote.R \name{remote_rename} \alias{remote_rename} \title{Rename a remote} \usage{ remote_rename(repo = ".", oldname = NULL, newname = NULL) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{oldname}{Old name of the remote} \item{newname}{New name of the remote} } \value{ NULL, invisibly } \description{ Rename a remote } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name="Alice", user.email="alice@example.org") writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Add a remote remote_add(repo, "playground", "https://example.org/git2r/playground") remotes(repo) remote_url(repo, "playground") ## Rename a remote remote_rename(repo, "playground", "foobar") remotes(repo) remote_url(repo, "foobar") ## Set remote url remote_set_url(repo, "foobar", "https://example.org/git2r/foobar") remotes(repo) remote_url(repo, "foobar") ## Remove a remote remote_remove(repo, "foobar") remotes(repo) } } git2r/man/tag_delete.Rd0000644000176200001440000000233214704742556014456 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/tag.R \name{tag_delete} \alias{tag_delete} \title{Delete an existing tag reference} \usage{ tag_delete(object = ".", name = NULL) } \arguments{ \item{object}{Can be either the path (default is ".") to a repository, or a \code{git_repository} object, or a \code{git_tag} object. or the tag name.} \item{name}{If the \code{object} argument is a path to a repository or a \code{git_repository}, the name of the tag to delete.} } \value{ \code{invisible(NULL)} } \description{ Delete an existing tag reference } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Commit a text file writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Create two tags tag(repo, "Tag1", "Tag message 1") t2 <- tag(repo, "Tag2", "Tag message 2") ## List the two tags in the repository tags(repo) ## Delete the two tags in the repository tag_delete(repo, "Tag1") tag_delete(t2) ## Show the empty list with tags in the repository tags(repo) } } git2r/man/odb_blobs.Rd0000644000176200001440000000357314704742556014316 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/odb.R \name{odb_blobs} \alias{odb_blobs} \title{Blobs in the object database} \usage{ odb_blobs(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ A data.frame with the following columns: \describe{ \item{sha}{The sha of the blob} \item{path}{The path to the blob from the tree and sub-trees} \item{name}{The name of the blob from the tree that contains the blob} \item{len}{The length of the blob} \item{commit}{The sha of the commit} \item{author}{The author of the commit} \item{when}{The timestamp of the author signature in the commit} } } \description{ List all blobs reachable from the commits in the object database. For each commit, list blob's in the commit tree and sub-trees. } \note{ A blob sha can have several entries } \examples{ \dontrun{ ## Create a directory in tempdir path <- tempfile(pattern="git2r-") dir.create(path) ## Initialize a repository repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Commit message 1") ## Change file and commit lines <- c( "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do", "eiusmod tempor incididunt ut labore et dolore magna aliqua.") writeLines(lines, file.path(path, "test.txt")) add(repo, "test.txt") commit(repo, "Commit message 2") ## Commit same content under different name in a sub-directory dir.create(file.path(path, "sub-directory")) file.copy(file.path(path, "test.txt"), file.path(path, "sub-directory", "copy.txt")) add(repo, "sub-directory/copy.txt") commit(repo, "Commit message 3") ## List blobs odb_blobs(repo) } } git2r/man/summary.git_repository.Rd0000644000176200001440000000207314704742556017141 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{summary.git_repository} \alias{summary.git_repository} \title{Summary of repository} \usage{ \method{summary}{git_repository}(object, ...) } \arguments{ \item{object}{The repository \code{object}} \item{...}{Additional arguments affecting the summary produced.} } \value{ None (invisible 'NULL'). } \description{ Summary of repository } \examples{ \dontrun{ ## Initialize a repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Config user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file writeLines("Hello world!", file.path(path, "test.txt")) summary(repo) ## Add file add(repo, "test.txt") summary(repo) ## Commit commit(repo, "First commit message") summary(repo) ## Change the file writeLines(c("Hello again!", "Here is a second line", "And a third"), file.path(path, "test.txt")) summary(repo) ## Add file and commit add(repo, "test.txt") commit(repo, "Second commit message") summary(repo) } } git2r/man/repository.Rd0000644000176200001440000000327314704742556014605 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{repository} \alias{repository} \title{Open a repository} \usage{ repository(path = ".", discover = TRUE) } \arguments{ \item{path}{A path to an existing local git repository.} \item{discover}{Discover repository from path. Default is TRUE.} } \value{ A \code{git_repository} object with entries: \describe{ \item{path}{ Path to a git repository } } } \description{ Open a repository } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) # Configure a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit writeLines("Hello world!", file.path(path, "test-1.txt")) add(repo, 'test-1.txt') commit_1 <- commit(repo, "Commit message") ## Make one more commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test-1.txt")) add(repo, 'test-1.txt') commit(repo, "Next commit message") ## Create one more file writeLines("Hello world!", file.path(path, "test-2.txt")) ## Brief summary of repository repo ## Summary of repository summary(repo) ## Workdir of repository workdir(repo) ## Check if repository is bare is_bare(repo) ## Check if repository is empty is_empty(repo) ## Check if repository is a shallow clone is_shallow(repo) ## List all references in repository references(repo) ## List all branches in repository branches(repo) ## Get HEAD of repository repository_head(repo) ## Check if HEAD is head is_head(repository_head(repo)) ## Check if HEAD is local is_local(repository_head(repo)) ## List all tags in repository tags(repo) } } git2r/man/repository_head.Rd0000644000176200001440000000157614704742556015572 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{repository_head} \alias{repository_head} \title{Get HEAD for a repository} \usage{ repository_head(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ NULL if unborn branch or not found. A git_branch if not a detached head. A git_commit if detached head } \description{ Get HEAD for a repository } \examples{ \dontrun{ ## Create and initialize a repository in a temporary directory path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "Commit message") ## Get HEAD of repository repository_head(repo) } } git2r/man/lookup.Rd0000644000176200001440000000301014704742556013664 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{lookup} \alias{lookup} \title{Lookup} \usage{ lookup(repo = ".", sha = NULL) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{sha}{The identity of the object to lookup. Must be 4 to 40 characters long.} } \value{ a \code{git_blob} or \code{git_commit} or \code{git_tag} or \code{git_tree} object } \description{ Lookup one object in a repository. } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "First commit message") ## Create tag tag(repo, "Tagname", "Tag message") ## First, get SHAs to lookup in the repository sha_commit <- sha(commit_1) sha_tree <- sha(tree(commit_1)) sha_blob <- sha(tree(commit_1)["example.txt"]) sha_tag <- sha(tags(repo)[[1]]) ## SHAs sha_commit sha_tree sha_blob sha_tag ## Lookup objects lookup(repo, sha_commit) lookup(repo, sha_tree) lookup(repo, sha_blob) lookup(repo, sha_tag) ## Lookup objects, using only the first seven characters lookup(repo, substr(sha_commit, 1, 7)) lookup(repo, substr(sha_tree, 1, 7)) lookup(repo, substr(sha_blob, 1, 7)) lookup(repo, substr(sha_tag, 1, 7)) } } git2r/man/workdir.Rd0000644000176200001440000000121414704742556014040 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/repository.R \name{workdir} \alias{workdir} \title{Workdir of repository} \usage{ workdir(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ Character vector with the path of the workdir. If the repository is bare, \code{NULL} will be returned. } \description{ Workdir of repository } \examples{ \dontrun{ ## Create a directory in tempdir path <- tempfile(pattern="git2r-") dir.create(path) ## Initialize a repository repo <- init(path) ## Get the path of the workdir for repository workdir(repo) } } git2r/man/cred_env.Rd0000644000176200001440000000252414704742555014150 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/credential.R \name{cred_env} \alias{cred_env} \title{Create a new environmental credential object} \usage{ cred_env(username = NULL, password = NULL) } \arguments{ \item{username}{The name of the environmental variable that holds the username for the authentication.} \item{password}{The name of the environmental variable that holds the password for the authentication.} } \value{ A list of class \code{cred_env} with entries: \describe{ \item{username}{ The name of the environmental variable that holds the username for the authentication. } \item{password}{ The name of the environmental variable that holds the password for the authentication. } } } \description{ Environmental variables can be written to the file \code{.Renviron}. This file is read by \emph{R} during startup, see \code{\link[base]{Startup}}. } \examples{ \dontrun{ ## Create an environmental credential object for the username and ## password. cred <- cred_env("NAME_OF_ENV_VARIABLE_WITH_USERNAME", "NAME_OF_ENV_VARIABLE_WITH_PASSWORD") repo <- repository("git2r") push(repo, credentials = cred) } } \seealso{ Other git credential functions: \code{\link{cred_ssh_key}()}, \code{\link{cred_token}()}, \code{\link{cred_user_pass}()} } \concept{git credential functions} git2r/man/note_create.Rd0000644000176200001440000000324614704742555014655 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/note.R \name{note_create} \alias{note_create} \title{Add note for a object} \usage{ note_create( object = NULL, message = NULL, ref = NULL, author = NULL, committer = NULL, force = FALSE ) } \arguments{ \item{object}{The object to annotate (git_blob, git_commit or git_tree).} \item{message}{Content of the note to add} \item{ref}{Canonical name of the reference to use. Default is \code{note_default_ref}.} \item{author}{Signature of the notes note author} \item{committer}{Signature of the notes note committer} \item{force}{Overwrite existing note. Default is FALSE} } \value{ git_note } \description{ Add note for a object } \examples{ \dontrun{ ## Create and initialize a repository in a temporary directory path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) config(repo, user.name = "Alice", user.email = "alice@example.org") ## Create a file, add and commit writeLines("Hello world!", file.path(path, "example.txt")) add(repo, "example.txt") commit_1 <- commit(repo, "Commit message 1") ## Create another commit writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "example.txt")) add(repo, "example.txt") commit_2 <- commit(repo, "Commit message 2") ## Check that notes is an empty list notes(repo) ## Create note in default namespace note_create(commit_1, "Note-1") ## Create note in named (review) namespace note_create(commit_1, "Note-2", ref="refs/notes/review") note_create(commit_2, "Note-3", ref="review") ## Create note on blob and tree note_create(tree(commit_1), "Note-4") note_create(tree(commit_1)["example.txt"], "Note-5") } } git2r/man/fetch.Rd0000644000176200001440000000524314704742555013455 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/fetch.R \name{fetch} \alias{fetch} \title{Fetch new data and update tips} \usage{ fetch( repo = ".", name = NULL, credentials = NULL, verbose = TRUE, refspec = NULL ) } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} \item{name}{the remote's name} \item{credentials}{The credentials for remote repository access. Default is NULL. To use and query an ssh-agent for the ssh key credentials, let this parameter be NULL (the default).} \item{verbose}{Print information each time a reference is updated locally. Default is \code{TRUE}.} \item{refspec}{The refs to fetch and which local refs to update, see examples. Pass NULL to use the \code{remote..fetch} variable. Default is \code{NULL}.} } \value{ invisible list of class \code{git_transfer_progress} with statistics from the fetch operation: \describe{ \item{total_objects}{ Number of objects in the packfile being downloaded } \item{indexed_objects}{ Received objects that have been hashed } \item{received_objects}{ Objects which have been downloaded } \item{total_deltas}{ Total number of deltas in the pack } \item{indexed_deltas}{ Deltas which have been indexed } \item{local_objects}{ Locally-available objects that have been injected in order to fix a thin pack } \item{received_bytes}{ Size of the packfile received up to now } } } \description{ Fetch new data and update tips } \examples{ \dontrun{ ## Initialize three temporary repositories path_bare <- tempfile(pattern="git2r-") path_repo_1 <- tempfile(pattern="git2r-") path_repo_2 <- tempfile(pattern="git2r-") dir.create(path_bare) dir.create(path_repo_1) dir.create(path_repo_2) bare_repo <- init(path_bare, bare = TRUE) repo_1 <- clone(path_bare, path_repo_1) repo_2 <- clone(path_bare, path_repo_2) config(repo_1, user.name = "Alice", user.email = "alice@example.org") config(repo_2, user.name = "Bob", user.email = "bob@example.org") ## Add changes to repo 1 writeLines("Lorem ipsum dolor sit amet", con = file.path(path_repo_1, "example.txt")) add(repo_1, "example.txt") commit(repo_1, "Commit message") ## Push changes from repo 1 to origin (bare_repo) push(repo_1, "origin", "refs/heads/master") ## Fetch changes from origin (bare_repo) to repo 2 fetch(repo_2, "origin") ## List updated heads fetch_heads(repo_2) ## Checking out GitHub pull requests locally path <- tempfile(pattern="ghit-") repo <- clone("https://github.com/leeper/ghit", path) fetch(repo, "origin", refspec = "pull/13/head:refs/heads/BRANCHNAME") checkout(repo, "BRANCHNAME") summary(repo) } } git2r/man/default_signature.Rd0000644000176200001440000000151614704742556016071 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/signature.R \name{default_signature} \alias{default_signature} \title{Get the signature} \usage{ default_signature(repo = ".") } \arguments{ \item{repo}{a path to a repository or a \code{git_repository} object. Default is '.'} } \value{ A \code{git_signature} object with entries: } \description{ Get the signature according to the repository's configuration } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Create a user config(repo, user.name = "Alice", user.email = "alice@example.org") ## Get the default signature default_signature(repo) ## Change user config(repo, user.name = "Bob", user.email = "bob@example.org") ## Get the default signature default_signature(repo) } } git2r/man/branch_target.Rd0000644000176200001440000000154614704742555015171 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/branch.R \name{branch_target} \alias{branch_target} \title{Get target (sha) pointed to by a branch} \usage{ branch_target(branch = NULL) } \arguments{ \item{branch}{The branch} } \value{ sha or NA if not a direct reference } \description{ Get target (sha) pointed to by a branch } \examples{ \dontrun{ ## Initialize a temporary repository path <- tempfile(pattern="git2r-") dir.create(path) repo <- init(path) ## Config user and commit a file config(repo, user.name = "Alice", user.email = "alice@example.org") lines <- "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do" writeLines(lines, file.path(path, "example.txt")) add(repo, "example.txt") commit(repo, "First commit message") ## Get target (sha) pointed to by 'master' branch branch_target(repository_head(repo)) } } git2r/DESCRIPTION0000644000176200001440000000443514705305562013024 0ustar liggesusersType: Package Package: git2r Title: Provides Access to Git Repositories Authors@R: c(person("Stefan", "Widgren", role = c("aut", "cre"), email = "stefan.widgren@gmail.com", comment = c(ORCID = "0000-0001-5745-2284")), person("Gabor", "Csardi", role = "ctb"), person("Gregory", "Jefferis", role = "ctb"), person("Jennifer", "Bryan", role = "ctb"), person("Jeroen", "Ooms", role = "ctb"), person("Jim", "Hester", role = "ctb"), person("John", "Blischak", role = "ctb"), person("Karthik", "Ram", role = "ctb"), person("Peter", "Carbonetto", role = "ctb"), person("Scott", "Chamberlain", role = "ctb"), person("Thomas", "Rosendal", role = "ctb")) Description: Interface to the 'libgit2' library, which is a pure C implementation of the 'Git' core methods. Provides access to 'Git' repositories to extract data and running some basic 'Git' commands. Version: 0.35.0 License: GPL-2 URL: https://docs.ropensci.org/git2r/, https://github.com/ropensci/git2r BugReports: https://github.com/ropensci/git2r/issues Imports: graphics, utils Depends: R (>= 4.0) Suggests: getPass NeedsCompilation: yes SystemRequirements: libgit2 (>= 1.0): libgit2-devel (rpm) or libgit2-dev (deb) Collate: 'blame.R' 'blob.R' 'branch.R' 'bundle_r_package.R' 'checkout.R' 'commit.R' 'config.R' 'contributions.R' 'credential.R' 'diff.R' 'fetch.R' 'git2r.R' 'index.R' 'libgit2.R' 'merge.R' 'note.R' 'odb.R' 'plot.R' 'pull.R' 'punch_card.R' 'push.R' 'reference.R' 'reflog.R' 'refspec.R' 'remote.R' 'repository.R' 'reset.R' 'revparse.R' 'sha.R' 'signature.R' 'stash.R' 'status.R' 'tag.R' 'time.R' 'tree.R' 'when.R' Encoding: UTF-8 RoxygenNote: 7.3.2 Packaged: 2024-10-20 07:43:12 UTC; stefan Author: Stefan Widgren [aut, cre] (), Gabor Csardi [ctb], Gregory Jefferis [ctb], Jennifer Bryan [ctb], Jeroen Ooms [ctb], Jim Hester [ctb], John Blischak [ctb], Karthik Ram [ctb], Peter Carbonetto [ctb], Scott Chamberlain [ctb], Thomas Rosendal [ctb] Maintainer: Stefan Widgren Repository: CRAN Date/Publication: 2024-10-20 23:00:02 UTC