Skip to content

Commit 15d0b08

Browse files
committed
Documentation
1 parent 5a3df36 commit 15d0b08

15 files changed

+611
-161
lines changed

R/file-mapping.R

+63-15
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,59 @@
11
#' Create a file mapping for multi-repository deployment
22
#'
3+
#' This function builds a mapping between local files and their target paths in repositories,
4+
#' supporting both individual file mapping and bulk directory processing.
5+
#'
36
#' @param ... Named arguments where names are local file paths and values are repository paths
47
#' @param dir Character string specifying a directory to search for files. Default is NULL.
58
#' @param pattern Character string with a regular expression pattern to match files in dir. Default is NULL.
69
#' @param target_prefix Character string to prefix to all target paths. Default is "".
710
#' @param preserve_structure Logical indicating whether to preserve directory structure in target. Default is FALSE.
11+
#' @param quiet Logical; if TRUE, suppresses information messages. Default is FALSE.
12+
#'
13+
#' @return
14+
#' Returns an object of class `"file_mapping"` (which is just a marked up `"list"`) containing:
15+
#'
16+
#' - A named list where each entry maps a local file path (name) to a target repository path (value)
17+
#' - Each key is the full path to a local file
18+
#' - Each value is the corresponding path where the file should be placed in repositories
819
#'
9-
#' @return A named list where names are local file paths and values are repository paths
20+
#' @seealso [`print.file_mapping()`] to display the mapping in a formatted way.
21+
#'
22+
#' @details
23+
#' The `dir` argument requires a valid directory path currently on the local filesystem.
24+
#' This directory is scanned for files matching the `pattern` regular expression,
25+
#' and each file is mapped to a target path in repositories. If the directory is
26+
#' not found, an error is thrown.
27+
#'
28+
#'
1029
#' @export
1130
#'
1231
#' @examples
13-
#' \dontrun{
14-
#' # Individual files
32+
#' # Map individual files with explicit source-to-target paths
1533
#' mapping <- file_mapping(
1634
#' "local/path/ci.yml" = ".github/workflows/ci.yml",
1735
#' "local/path/lint.R" = ".lintr"
1836
#' )
1937
#'
20-
#' # All yaml files from a directory to .github/workflows
21-
#' mapping <- file_mapping(
22-
#' dir = "local/workflows",
23-
#' pattern = "\\.ya?ml$",
24-
#' target_prefix = ".github/workflows/"
38+
#' # Automatically map all R files from a directory to backup/R2/
39+
#' workflow_mapping <- file_mapping(
40+
#' dir = system.file(package = "multideploy"),
41+
#' pattern = "\\.R$",
42+
#' target_prefix = "backup/R2/"
2543
#' )
2644
#'
27-
#' # Preserve directory structure
28-
#' mapping <- file_mapping(
29-
#' dir = "templates",
45+
#' # Preserve directory structure when mapping files
46+
#' template_mapping <- file_mapping(
47+
#' dir = system.file(package = "multideploy"),
3048
#' preserve_structure = TRUE
3149
#' )
32-
#' }
50+
#'
51+
#' # Combine explicit mappings with directory-based mappings
52+
#' combined_mapping <- file_mapping(
53+
#' "specific/file.R" = "R/functions.R",
54+
#' dir = system.file(package = "multideploy"),
55+
#' target_prefix = ".github/"
56+
#' )
3357
file_mapping <- function(..., dir = NULL, pattern = NULL,
3458
target_prefix = "", preserve_structure = FALSE, quiet = FALSE) {
3559
mapping <- list(...)
@@ -79,12 +103,36 @@ file_mapping <- function(..., dir = NULL, pattern = NULL,
79103

80104
#' Print method for file_mapping objects
81105
#'
82-
#' @param x A file_mapping object to print
106+
#' This method provides a formatted display of file mappings, showing the relationship between
107+
#' local files and their target repository paths with visual indicators for file existence.
108+
#'
109+
#' @param x An object of class `"file_mapping"` as returned by `file_mapping()`
83110
#' @param max_files Maximum number of files to display. Default is 20.
84-
#' @param ... Additional arguments passed to print methods (not used)
111+
#' @param ... Additional arguments passed to other print methods (not used)
112+
#'
113+
#' @return
114+
#' Invisibly returns the original `file_mapping` object unchanged, allowing for
115+
#' chained operations.
116+
#'
117+
#' Displays a formatted representation of the mapping to the console, including:
118+
#'
119+
#' - Total count of mapped files
120+
#' - Visual indicators showing which local files exist (checkmark) or are missing (x)
121+
#' - Source-to-target mapping for each file (limited by `max_files`)
85122
#'
86-
#' @return Invisibly returns the file_mapping object
87123
#' @export
124+
#'
125+
#' @examples
126+
#' # Create and display a mapping
127+
#' mapping <- file_mapping(
128+
#' "R/functions.R" = "R/utils.R",
129+
#' dir = system.file(package = "multideploy")
130+
#' )
131+
#' # The mapping is automatically printed when not assigned
132+
#'
133+
#' # Control how many files are displayed
134+
#' mapping <- file_mapping(dir = system.file(package = "multideploy"))
135+
#' print(mapping, max_files = 5) # Show only first 5 mappings
88136
print.file_mapping <- function(x, max_files = 20, ...) {
89137
n_files <- length(x)
90138

R/file.R

+130-40
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,39 @@
11
#' Retrieve the content of a file from a GitHub repository
22
#'
3-
#' @param repo Character string specifying the full name of the repository (owner/repo)
4-
#' @param path Character string specifying the path to the file
5-
#' @param ref Character string specifying the branch name or commit SHA. Default is NULL.
3+
#' This function fetches a file from a GitHub repository and returns its content and SHA.
4+
#' If the file cannot be retrieved, it returns NULL and optionally displays a warning message.
5+
#'
6+
#' @param repo Character string specifying the full name of the repository (format: "owner/repo")
7+
#' @param path Character string specifying the path to the file within the repository
8+
#' @param ref Character string specifying the branch name, tag, or commit SHA. Default is NULL (uses default branch).
9+
#'
10+
#' @return
11+
#' When successful, returns a `list` with two elements:
12+
#'
13+
#' \describe{
14+
#' \item{content}{Character string containing the decoded file content}
15+
#' \item{sha}{Character string with the file's blob SHA for use in update operations}
16+
#' }
17+
#'
18+
#' When the file cannot be retrieved (e.g., does not exist or no access), returns `NULL`.
619
#'
7-
#' @return List with the content and SHA of the file if it exists, NULL otherwise
820
#' @export
921
#'
10-
#' @examples
11-
#' \dontrun{
12-
#' file_info <- file_content("username/repo", "path/to/file.R")
22+
#' @examplesIf interactive()
23+
#' # Get content from default branch
24+
#' file_info <- file_content("username/repository", "path/to/file.R")
25+
#' if (!is.null(file_info)) {
26+
#' # Access the content and SHA
27+
#' content <- file_info$content
28+
#' sha <- file_info$sha
1329
#' }
14-
file_content <- function(repo, path, ref = NULL, quiet = FALSE) {
30+
#'
31+
#' # Get content from specific branch
32+
#' file_info <- file_content("username/repository", "path/to/file.R", ref = "develop")
33+
#'
34+
#' # Suppress warnings
35+
#' file_info <- file_content("username/repository", "path/to/file.R")
36+
file_content <- function(repo, path, ref = NULL) {
1537
tryCatch({
1638
query <- list(path = path)
1739
if (!is.null(ref)) {
@@ -33,28 +55,62 @@ file_content <- function(repo, path, ref = NULL, quiet = FALSE) {
3355
return(NULL)
3456
}
3557
}, error = function(e) {
36-
if (!quiet) {
37-
cli::cli_alert_warning("Could not fetch file {.file {path}} from {.val {repo}}: {e$message}")
38-
}
58+
cli::cli_alert_warning("Could not fetch file {.file {path}} from {.val {repo}}: {e$message}")
3959
return(NULL)
4060
})
4161
}
4262

4363
#' Create or update a file in a GitHub repository
4464
#'
45-
#' @param repo Character string specifying the full name of the repository (owner/repo)
46-
#' @param path Character string specifying the path to the file
65+
#' This function creates a new file or updates an existing file in a GitHub repository.
66+
#' For updating existing files, the SHA of the current file must be provided.
67+
#'
68+
#' @param repo Character string specifying the full name of the repository (format: "owner/repo")
69+
#' @param path Character string specifying the path to the file within the repository
4770
#' @param content Character string with the new content of the file
4871
#' @param message Character string with the commit message
4972
#' @param branch Character string specifying the branch name. Default is NULL (uses default branch).
50-
#' @param sha Character string with the blob SHA of the file being replaced (required for updates). Default is NULL.
73+
#' @param sha Character string with the blob SHA of the file being replaced. Required for updating
74+
#' existing files; omit for creating new files. Default is NULL.
75+
#' @param quiet Logical; if TRUE, suppresses progress and status messages. Default is FALSE.
76+
#'
77+
#' @return
78+
#' When successful, returns a `list` containing the GitHub API response with details about the commit,
79+
#' including:
80+
#'
81+
#' \describe{
82+
#' \item{content}{Information about the updated file}
83+
#' \item{commit}{Details about the created commit}
84+
#' }
85+
#'
86+
#' When the operation fails (e.g., permission issues, invalid SHA), returns `NULL`.
5187
#'
52-
#' @return A list with the API response or NULL if operation failed
5388
#' @export
5489
#'
55-
#' @examples
56-
#' \dontrun{
57-
#' result <- file_update("username/repo", "path/to/file.R", "new content", "Update file")
90+
#' @examplesIf interactive()
91+
#' # Create a new file
92+
#' result <- file_update(
93+
#' repo = "username/repository",
94+
#' path = "path/to/new_file.R",
95+
#' content = "# New R script\n\nprint('Hello world')",
96+
#' message = "Add new script file"
97+
#' )
98+
#' # Check if operation was successful
99+
#' if (!is.null(result)) {
100+
#' # Access commit information
101+
#' commit_sha <- result$commit$sha
102+
#' }
103+
#'
104+
#' # Update an existing file (requires SHA)
105+
#' file_info <- file_content("username/repository", "path/to/existing_file.R")
106+
#' if (!is.null(file_info)) {
107+
#' result <- file_update(
108+
#' repo = "username/repository",
109+
#' path = "path/to/existing_file.R",
110+
#' content = "# Updated content\n\nprint('Hello updated world')",
111+
#' message = "Update file content",
112+
#' sha = file_info$sha
113+
#' )
58114
#' }
59115
file_update <- function(repo, path, content, message, branch = NULL, sha = NULL, quiet = FALSE) {
60116
tryCatch({
@@ -84,7 +140,6 @@ file_update <- function(repo, path, content, message, branch = NULL, sha = NULL,
84140
),
85141
query
86142
))
87-
88143
if (!quiet) {
89144
if (operation == "create") {
90145
cli::cli_alert_success("Created file {.file {path}} in {.val {repo}}")
@@ -97,31 +152,55 @@ file_update <- function(repo, path, content, message, branch = NULL, sha = NULL,
97152

98153
}, error = function(e) {
99154
operation_name <- ifelse(is.null(sha), "creating", "updating")
100-
if (!quiet) {
101-
cli::cli_alert_danger("Error {operation_name} file {.file {path}} in {.val {repo}}: {e$message}")
102-
}
155+
cli::cli_alert_danger("Error {operation_name} file {.file {path}} in {.val {repo}}: {e$message}")
103156
return(NULL)
104157
})
105158
}
106159

107160
#' Deploy a file to multiple GitHub repositories
108161
#'
162+
#' This function deploys a local file to multiple GitHub repositories. It can create new files
163+
#' or update existing ones, and provides detailed status reporting for each operation.
164+
#'
109165
#' @param source_file Character string specifying the local file path to deploy
110166
#' @param target_path Character string specifying the path in the repositories where the file should be placed
111-
#' @param repos Data frame of repositories as returned by repos()
112-
#' @param commit_message Character string with the commit message. Default uses a standard message.
167+
#' @param repos Data frame of repositories as returned by `repos()` function, with at least a `full_name` column
168+
#' @param commit_message Character string with the commit message. Default automatically generates a message.
113169
#' @param branch Character string specifying the branch name. Default is NULL (uses default branch).
114170
#' @param create_if_missing Logical indicating whether to create the file if it doesn't exist. Default is TRUE.
115-
#' @param dry_run Logical indicating whether to only simulate the changes without actually making them. Default is FALSE.
171+
#' @param dry_run Logical indicating whether to only simulate the changes without making actual commits. Default is FALSE.
172+
#' @param quiet Logical; if TRUE, suppresses progress and status messages. Default is FALSE.
173+
#'
174+
#' @return
175+
#' Returns a `data.frame` with class `"file_deploy_result"` containing the following columns:
176+
#'
177+
#' \describe{
178+
#' \item{repository}{Character, the full repository name (owner/repo)}
179+
#' \item{status}{Character, indicating the operation result with one of these values:
180+
#' "created", "updated", "unchanged", "skipped", "error", "would_create", "would_update"}
181+
#' \item{message}{Character, a description of the action taken or error encountered}
182+
#' }
183+
#'
184+
#' @seealso [`print.file_deploy_result()`] for a formatted summary of deployment results.
116185
#'
117-
#' @return A data frame with the results of each deployment
118186
#' @export
119187
#'
120-
#' @examples
121-
#' \dontrun{
122-
#' repositories <- repos("myorg")
123-
#' results <- file_deploy("local/path/to/file.R", ".github/workflows/ci.yml", repositories)
124-
#' }
188+
#' @examplesIf interactive()
189+
#' # Get list of repositories
190+
#' repositories <- repos("my-organization")
191+
#'
192+
#' # Deploy a workflow file to all repositories
193+
#' results <- file_deploy(
194+
#' source_file = "local/path/to/workflow.yml",
195+
#' target_path = ".github/workflows/ci.yml",
196+
#' repos = repositories
197+
#' )
198+
#'
199+
#' # Filter to see only successfully updated repositories
200+
#' updated <- results[results$status == "updated", ]
201+
#'
202+
#' # Check for any errors
203+
#' errors <- results[results$status == "error", ]
125204
file_deploy <- function(source_file, target_path, repos,
126205
commit_message = NULL, branch = NULL,
127206
create_if_missing = TRUE, dry_run = FALSE, quiet = FALSE) {
@@ -134,7 +213,7 @@ file_deploy <- function(source_file, target_path, repos,
134213
file_content <- readChar(source_file, file.info(source_file)$size)
135214

136215
if (is.null(commit_message)) {
137-
commit_message <- sprintf("Update %s via multi.gh automated deployment", target_path)
216+
commit_message <- sprintf("Update %s via multideploy automated deployment", target_path)
138217
}
139218

140219
# Initialize results data frame
@@ -215,19 +294,30 @@ file_deploy <- function(source_file, target_path, repos,
215294
return(results)
216295
}
217296

218-
#' Print method for file_deploy_result objects
297+
#' Print method for `"file_deploy_result"` objects
298+
#'
299+
#' This method provides a formatted summary of file deployment results,
300+
#' showing counts by status and details for any errors encountered.
219301
#'
220-
#' @param x The file_deploy_result object to print
221-
#' @param ... Additional arguments to pass to print methods
302+
#' @param x An object of class `"file_deploy_result"` as returned by `file_deploy()`
303+
#' @param ... Additional arguments passed to other print methods (not used)
304+
#'
305+
#' @return
306+
#' Invisibly returns the original input data frame unchanged.
307+
#'
308+
#' Displays a formatted summary of deployment results to the console.
222309
#'
223-
#' @return Invisibly returns the input data frame
224310
#' @export
225311
#'
226-
#' @examples
227-
#' \dontrun{
228-
#' results <- file_deploy("local/file.R", "remote/file.R", repos)
312+
#' @examplesIf interactive()
313+
#' # Get list of repositories
314+
#' repositories <- repos("my-organization")
315+
#'
316+
#' # Deploy files
317+
#' results <- file_deploy("local/file.R", "remote/file.R", repositories)
318+
#'
319+
#' # Explicitly print the summary
229320
#' print(results)
230-
#' }
231321
print.file_deploy_result <- function(x, ...) {
232322
# Summary
233323
status_counts <- table(x$status)

0 commit comments

Comments
 (0)