1## git2r, R bindings to the libgit2 library.
2## Copyright (C) 2013-2019 The git2r contributors
3##
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License, version 2,
6## as published by the Free Software Foundation.
7##
8## git2r is distributed in the hope that it will be useful,
9## but WITHOUT ANY WARRANTY; without even the implied warranty of
10## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11## GNU General Public License for more details.
12##
13## You should have received a copy of the GNU General Public License along
14## with this program; if not, write to the Free Software Foundation, Inc.,
15## 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
17library(git2r)
18source("util/check.R")
19
20## For debugging
21sessionInfo()
22
23## Create a directory in tempdir
24path <- tempfile(pattern = "git2r-")
25dir.create(path)
26
27## Initialize a repository
28repo <- init(path)
29config(repo, user.name = "Alice", user.email = "alice@example.org")
30
31## Commit without adding changes should produce an error
32tools::assertError(commit(repo, "Test to commit"))
33
34## Create a file
35writeLines("Hello world!", file.path(path, "test.txt"))
36
37## Commit without adding changes should produce an error
38tools::assertError(commit(repo, "Test to commit"))
39
40## Add
41add(repo, "test.txt")
42
43## Commit with empty message should produce an error
44tools::assertError(commit(repo, ""))
45
46## Commit
47commit_1 <- commit(repo, "Commit message", session = TRUE)
48summary(commit_1)
49tag_1 <- tag(repo, "Tagname1", "Tag message 1")
50
51## Check commit
52stopifnot(identical(commit_1$author$name, "Alice"))
53stopifnot(identical(commit_1$author$email, "alice@example.org"))
54stopifnot(identical(lookup(repo, sha(commit_1)), commit_1))
55stopifnot(identical(length(commits(repo)), 1L))
56stopifnot(identical(commits(repo)[[1]]$author$name, "Alice"))
57stopifnot(identical(commits(repo)[[1]]$author$email, "alice@example.org"))
58stopifnot(identical(parents(commit_1), list()))
59stopifnot(identical(print(commit_1), commit_1))
60
61## Check is_commit
62stopifnot(identical(is_commit(commit_1), TRUE))
63stopifnot(identical(is_commit(5), FALSE))
64
65## Commit without adding changes should produce an error
66tools::assertError(commit(repo, "Test to commit"))
67
68## Add another commit
69writeLines(c("Hello world!", "HELLO WORLD!"), file.path(path, "test.txt"))
70add(repo, "test.txt")
71commit_2 <- commit(repo, "Commit message 2")
72summary(commit_2)
73tag_2 <- tag(repo, "Tagname2", "Tag message 2")
74
75## Check relationship
76stopifnot(identical(descendant_of(commit_2, commit_1), TRUE))
77stopifnot(identical(descendant_of(commit_1, commit_2), FALSE))
78stopifnot(identical(descendant_of(tag_2, tag_1), TRUE))
79stopifnot(identical(descendant_of(tag_1, tag_2), FALSE))
80stopifnot(identical(descendant_of(branches(repo)[[1]], commit_1), TRUE))
81stopifnot(identical(descendant_of(commit_1, branches(repo)[[1]]), FALSE))
82stopifnot(identical(length(parents(commit_2)), 1L))
83stopifnot(identical(parents(commit_2)[[1]], commit_1))
84
85## Check contributions
86stopifnot(identical(
87    colnames(contributions(repo, by = "author", breaks = "day")),
88    c("when", "author", "n")))
89stopifnot(identical(colnames(contributions(repo)),
90                    c("when", "n")))
91stopifnot(identical(nrow(contributions(repo)), 1L))
92stopifnot(identical(contributions(repo)$n, 2L))
93stopifnot(identical(contributions(repo, by = "author", breaks = "day")$n, 2L))
94
95## Add another commit with 'all' argument
96writeLines(c("Hello world!", "HELLO WORLD!", "HeLlO wOrLd!"),
97           file.path(path, "test.txt"))
98commit(repo, "Commit message 3", all = TRUE)
99
100status_clean <- structure(list(staged = empty_named_list(),
101                               unstaged = empty_named_list(),
102                               untracked = empty_named_list()),
103                          class = "git_status")
104stopifnot(identical(status(repo), status_clean))
105
106## Delete file and commit with 'all' argument
107file.remove(file.path(path, "test.txt"))
108commit(repo, "Commit message 4", all = TRUE)
109
110stopifnot(identical(status(repo), status_clean))
111
112## Add and commit multiple tracked files with 'all' argument
113writeLines(sample(letters, 3), file.path(path, "test2.txt"))
114add(repo, "test2.txt")
115writeLines(sample(letters, 3), file.path(path, "test3.txt"))
116add(repo, "test3.txt")
117writeLines(sample(letters, 3), file.path(path, "test4.txt"))
118add(repo, "test4.txt")
119commit(repo, "Commit message 5")
120
121stopifnot(identical(status(repo), status_clean))
122
123writeLines(sample(letters, 3), file.path(path, "test2.txt"))
124writeLines(sample(letters, 3), file.path(path, "test3.txt"))
125writeLines(sample(letters, 3), file.path(path, "test4.txt"))
126commit(repo, "Commit message 6", all = TRUE)
127
128stopifnot(identical(status(repo), status_clean))
129
130## Add one tracked file and delete another with 'all' argument
131writeLines(sample(letters, 3), file.path(path, "test2.txt"))
132file.remove(file.path(path, "test4.txt"))
133commit(repo, "Commit message 7", all = TRUE)
134
135stopifnot(identical(status(repo), status_clean))
136
137## Delete multiple tracked files with 'all' argument
138file.remove(file.path(path, "test2.txt"))
139file.remove(file.path(path, "test3.txt"))
140commit(repo, "Commit message 8", all = TRUE)
141
142stopifnot(identical(status(repo), status_clean))
143
144## Check max number of commits in output
145stopifnot(identical(length(commits(repo)), 8L))
146stopifnot(identical(length(commits(repo, n = -1)), 8L))
147stopifnot(identical(length(commits(repo, n = 2)), 2L))
148tools::assertError(commits(repo, n = 2.2))
149tools::assertError(commits(repo, n = "2"))
150tools::assertError(commits(repo, n = 1:2))
151
152## Check to coerce repository to data.frame
153df <- as.data.frame(repo)
154stopifnot(identical(dim(df), c(8L, 6L)))
155stopifnot(identical(names(df), c("sha", "summary", "message",
156                                 "author", "email", "when")))
157
158## Set working directory to path and check commits
159setwd(path)
160stopifnot(identical(sha(last_commit()), sha(commits(repo, n = 1)[[1]])))
161stopifnot(identical(length(commits()), 8L))
162stopifnot(identical(length(commits(n = -1)), 8L))
163stopifnot(identical(length(commits(n = 2)), 2L))
164tools::assertError(commits(n = 2.2))
165tools::assertError(commits(n = "2"))
166
167## Check plot method
168plot_file <- tempfile(fileext = ".pdf")
169pdf(plot_file)
170plot(repo)
171dev.off()
172stopifnot(file.exists(plot_file))
173unlink(plot_file)
174
175## Check punch card plot method
176punch_card_plot_file <- tempfile(fileext = ".pdf")
177pdf(punch_card_plot_file)
178punch_card(repo)
179dev.off()
180stopifnot(file.exists(punch_card_plot_file))
181unlink(punch_card_plot_file)
182
183## Check that 'git2r_arg_check_commit' raise error
184res <- tools::assertError(.Call(git2r:::git2r_commit_tree, NULL))
185stopifnot(length(grep("'commit' must be an S3 class git_commit",
186                      res[[1]]$message)) > 0)
187res <- tools::assertError(.Call(git2r:::git2r_commit_tree, 3))
188stopifnot(length(grep("'commit' must be an S3 class git_commit",
189                      res[[1]]$message)) > 0)
190res <- tools::assertError(.Call(git2r:::git2r_commit_tree, repo))
191stopifnot(length(grep("'commit' must be an S3 class git_commit",
192                      res[[1]]$message)) > 0)
193commit_1$sha <- NA_character_
194res <- tools::assertError(.Call(git2r:::git2r_commit_tree, commit_1))
195stopifnot(length(grep("'commit' must be an S3 class git_commit",
196                      res[[1]]$message)) > 0)
197
198## Cleanup
199unlink(path, recursive = TRUE)
200
201if (identical(Sys.getenv("NOT_CRAN"), "true") ||
202    identical(Sys.getenv("R_COVR"), "true")) {
203    path <- tempfile(pattern = "git2r-")
204    dir.create(path)
205    setwd(path)
206    system("git clone --depth 2 https://github.com/ropensci/git2r.git")
207
208    ## Check the number of commits in the shallow clone.
209    stopifnot(identical(length(commits(repository("git2r"))), 2L))
210    stopifnot(identical(length(commits(repository("git2r"), n = 1)), 1L))
211
212    ## Cleanup
213    unlink(path, recursive = TRUE)
214}
215