Nothing
remote_info <- reactive({
input$sync
input$sync_unlink
input$branch_link
input$branch_unlink
req(input$repo_directory)
suppressWarnings(paste0(system(paste("git -C", input$repo_directory, "remote -v"), intern = TRUE), collapse = "\n")) %>%
gsub("(\t)|( ) ", " ", .)
})
upstream_info <- function() {
input$sync
input$sync_unlink
req(input$repo_directory)
suppressWarnings(system(paste("git -C", input$repo_directory, "remote -v"), intern = TRUE)) %>%
.[grepl("^upstream", .)] %>%
gsub("^upstream\\s+", "", .) %>%
gsub(" \\(fetch\\)$", "", .)
}
observeEvent(input$sync_stage, {
req(input$repo_directory)
withProgress(message = "Staging all files", value = 0, style = "old", {
system(paste("git -C", input$repo_directory, "add ."))
mess <- suppressWarnings(system(paste0("git -C ", input$repo_directory, " diff --staged"), intern = TRUE))
})
mess <- color_diff_html(mess)
if (is_empty(mess)) mess <- "No changes to commit"
showModal(
modalDialog(
title = "Staged file differences",
span(HTML(paste0(mess, collapse = "</br>"))),
size = "l",
easyClose = TRUE
)
)
})
observeEvent(input$sync_commit, {
req(input$repo_directory)
cmess <- input$sync_commit_message
req(input$repo_directory)
if (is_empty(cmess)) {
cmess <- paste0("Updates: ", Sys.time())
} else {
cmess <- gsub("\"", "'", cmess)
}
withProgress(message = "Committing all changes locally", value = 0, style = "old", {
system(paste("git -C", input$repo_directory, "add ."))
mess <- suppressWarnings(system(paste0("git -C ", input$repo_directory, " commit -m \"", cmess, "\""), intern = TRUE))
message("\nCommit attempt completed. Check the console for messages\n")
})
showModal(
modalDialog(
title = "Commit messages",
span(HTML(paste0(mess, collapse = "</br>")))
)
)
updateTextInput(session = session, "sync_commit_message", value = "")
})
## Show reset modal when button is clicked.
observeEvent(input$sync_undo_commit_show, {
## See https://shiny.rstudio.com/reference/shiny/latest/modalDialog.html
commit_mess <- system(paste("git -C", input$repo_directory, "log -1 --pretty=%B"), intern = TRUE)
req(input$repo_directory)
showModal(
modalDialog(
title = "Undo latest local commit",
span(suppressWarnings(paste0("\"", commit_mess[1], "\""))),
br(), br(),
span("Are you sure you want to undo the latest local commit? This will
leave the latest changes un-staged (see Rstudio Git tab) so you can
edit them or revert the changes"),
footer = tagList(
modalButton("Cancel"),
actionButton(
"sync_undo_commit", "Undo",
class = "btn-danger",
title = "Undo the latest local commit\n\nGit command:\ngit reset HEAD~"
)
)
)
)
})
observeEvent(input$sync_undo_commit, {
req(input$repo_directory)
withProgress(message = "Undo the latest local commit", value = 0, style = "old", {
system(paste("git -C", input$repo_directory, "reset HEAD~"))
message("\nPrevious changes are now unstaged. Check the Git tab in Rstudio\n")
})
removeModal()
updateTextInput(
session = session,
"sync_commit_message",
value = system(paste("git -C", input$repo_directory, "log -1 --pretty=%B"), intern = TRUE)
)
})
observeEvent(input$sync_pull, {
req(input$repo_directory)
mess_file <- tempfile()
withProgress(message = "Pull changes from remote", value = 0, style = "old", {
suppressWarnings(system(paste("git -C", input$repo_directory, "pull 2> ", mess_file)))
message("\nPull attempt completed. Check the console for messages\n")
})
mess <- paste0(readLines(mess_file), collapse = "\n")
if (is_empty(mess)) mess <- "Already up to date."
unlink(mess_file)
showModal(
modalDialog(
title = "Pull messages",
span(HTML(paste0(mess, collapse = "</br>")))
)
)
})
observeEvent(input$sync_push, {
req(input$repo_directory)
mess_file <- tempfile()
withProgress(message = "Pushing changes to remote", value = 0, style = "old", {
suppressWarnings(system(paste("git -C", input$repo_directory, "push 2> ", mess_file)))
message("\nPush attempt completed. Check the console for messages\n")
})
mess <- paste0(readLines(mess_file), collapse = "\n")
unlink(mess_file)
showModal(
modalDialog(
title = "Push messages",
span(HTML(paste0(mess, collapse = "</br>")))
)
)
})
output$ui_sync_check <- renderUI({
req(input$sync_check > 0)
assn <- assignment_name(github = FALSE, url = TRUE)
hash <- suppressWarnings(system(paste("git -C", input$repo_directory, "rev-parse --short HEAD"), intern = TRUE))
if (!is_empty(hash) && length(hash) == 1) {
assn <- paste0(assn, "/commit/", hash)
}
tags$script(paste0("window.open('", assn, "', '_blank')"))
})
## Show reset modal when button is clicked.
observeEvent(input$sync_reset_show, {
## See https://shiny.rstudio.com/reference/shiny/latest/modalDialog.html
showModal(
modalDialog(
title = "Reset local repo",
span("Are you sure you want to reset the local repo? Only use this
option if you want to destroy the current state of the local repo
and make a copy of the remote repo!"),
footer = tagList(
modalButton("Cancel"),
actionButton(
"sync_reset", "Reset",
class = "btn-danger",
title = "Completely reset local repo to remote main branch\n\nGit commands:\ngit --fetch all\ngit reset --hard origin/main"
)
)
)
)
})
observeEvent(input$sync_reset, {
removeModal()
req(input$repo_directory)
withProgress(message = "Resetting local repo to remote main branch", value = 0, style = "old", {
## Add confirmation dialog
mess1 <- system(paste("git -C", input$repo_directory, "fetch --all"), intern = TRUE)
mess2 <- system(paste("git -C", input$repo_directory, "reset --hard origin/main"), intern = TRUE)
message("\nReset attempt completed. Check the console for messages\n")
})
mess <- c(mess1, mess2)
showModal(
modalDialog(
title = "Reset messages",
span(HTML(paste0(mess, collapse = "</br>")))
)
)
})
observeEvent(input$sync, {
req(input$repo_directory)
if (!is_empty(input$sync_from)) {
withProgress(message = "Syncing repo", value = 0, style = "old", {
if (is_empty(upstream_info())) {
mess1 <- system(paste("git -C", input$repo_directory, "remote add upstream", input$sync_from), intern = TRUE)
mess2 <- system(paste("git -C", input$repo_directory, "fetch upstream"), intern = TRUE)
mess <- c(mess1, mess2)
showModal(
modalDialog(
title = "Reset messages",
span(HTML(paste0(mess, collapse = "</br>")))
)
)
}
})
}
})
observeEvent(input$sync_merge, {
req(input$repo_directory)
withProgress(message = "Merging synced repo", value = 0, style = "old", {
mess1 <- system(paste("git -C", input$repo_directory, "checkout main"), intern = TRUE)
mess2 <- system(paste("git -C", input$repo_directory, "merge upstream/main"), intern = TRUE)
})
mess <- c(mess1, mess2)
showModal(
modalDialog(
title = "Merge messages",
span(HTML(paste0(mess, collapse = "</br>")))
)
)
})
observeEvent(input$synch_abort, {
req(input$repo_directory)
mess <- system(paste("git -C", input$repo_directory, "merge --abort"), intern = TRUE)
showModal(
modalDialog(
title = "Merge abort messages",
span(HTML(paste0(mess, collapse = "</br>")))
)
)
})
observeEvent(input$sync_unlink, {
req(input$repo_directory)
mess <- system(paste("git -C", input$repo_directory, "remote remove upstream"), intern = TRUE)
showModal(
modalDialog(
title = "Unlink messages",
span(HTML(paste0(mess, collapse = "</br>")))
)
)
})
output$ui_sync_commit_message <- renderUI({
br <- rbranches()
if (length(br) == 0) {
HTML(paste0("<label>", input$repo_directory, " is not a git repo</label></br>"))
} else {
textAreaInput(
"sync_commit_message", "Commit message:",
rows = 2, resize = "both", value = "",
placeholder = "Provide a commit message that describes the changes you made to the repo"
)
}
})
output$ui_sync_from <- renderUI({
init <- upstream_info()
textInput(
"sync_from", "Sync repo with remote it was forked from:",
value = ifelse(length(init) == 0, "", init[1]),
placeholder = "Provide https or ssh link to original remote repo"
)
})
output$sync_output <- renderPrint({
cat("Overview of remotes:\n\n")
cat(remote_info())
})
color_diff_html <- function(mess) {
# adapted from https://gist.github.com/stopyoukid/5888146
html <- "<html> <head> <meta charset=\"utf-8\"> <style> .modal-lg .file-diff>div { width: 100%; } .modal-lg .modal-body { overflow: auto; } .modal-lg pre::-webkit-scrollbar { /* hide scrollbar on chrome, safari, and edge */ display: none; } .modal-lg pre { /* hide scrollbar on firefox */ scrollbar-width: none; } .modal-lg pre { padding: 0; margin: 0; margin-left: 5px; font-size: 12px; text-align: left; border: 0; border-radius: 0; background-color: rgb(255, 255, 255); line-height: 1.75em; } .modal-lg .file { margin-bottom: 1em; border: 1px; } .modal-lg .delete { background-color: #fdd; } .modal-lg .insert { background-color: #dfd; } .modal-lg .info { background-color: #888 } .modal-lg .context { color: #aaa; } </style> </head> <body>"
## for testing purposes
# html <- paste0(readLines("~/Desktop/format.html"), collapse = "\n")
first <- 1
diffseen <- lastonly <- 0
currSection <- currFile <- ""
addDiffToPage <- function(file, section, html) {
paste0(html, "\n<h2>", file, "</h2>\n") %>%
paste0("<div class=\"file-diff\">\n") %>%
paste0(section) %>%
paste0("\n</div>")
}
for (s in mess) {
# Get beginning of line to determine what type of diff line it is.
t1 <- substring(s, 0, 1)
t2 <- substring(s, 0, 2)
t3 <- substring(s, 0, 3)
t4 <- substring(s, 0, 4)
t7 <- substring(s, 0, 7)
cls <- ""
# Determine HTML class to use.
if (t7 == "Only in") {
cls <- "only"
if (diffseen == 0) {
diffseen <- 1
} else {
if (lastonly == 0) {
html <- addDiffToPage(currFile, currSection, html)
}
}
if (lastonly == 0) currSection <- ""
lastonly <- 1
} else if (t4 == "diff") {
cls <- "file"
s <- sub("^.* b/", ">>> ", s)
if (diffseen == 1) {
html <- addDiffToPage(currFile, currSection, html)
}
diffseen <- 1
currSection <- ""
lastonly <- 0
} else if (t3 == "+++") {
lastonly <- 0
next
} else if (t3 == "---") {
lastonly <- 0
next
} else if (t2 == "@@") {
cls <- "info"
lastonly <- 0
} else if (t1 == "+") {
s <- paste0(" ", substring(s, 2))
cls <- "insert"
lastonly <- 0
} else if (t1 == "-") {
s <- paste0(" ", substring(s, 2))
cls <- "delete"
lastonly <- 0
} else {
cls <- "context"
lastonly <- 0
}
# Convert &, <, > to HTML entities.
s <- gsub("\\&", "\\&", s) %>%
gsub("<", "\\<", .) %>%
gsub(">", "\\>", .)
if (first == 1) first <- 0
# Output the line.
if (cls != "") {
currSection <- paste0(currSection, "\n<pre class=\"", cls, "\">", s, "</pre>")
} else {
currSection <- paste0(currSection, "\n<pre>", s, "</pre>")
}
}
if (currSection != "") {
html <- addDiffToPage(currFile, currSection, html)
}
paste0(html, "\n</body></html>")
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.