From d28ff0c9086504f06611e529c590e704d4de69a2 Mon Sep 17 00:00:00 2001 From: Justin Yap Date: Fri, 3 Oct 2025 10:57:28 +1000 Subject: [PATCH 01/16] Create check-copilot-instructions.yml --- .../workflows/check-copilot-instructions.yml | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 .github/workflows/check-copilot-instructions.yml diff --git a/.github/workflows/check-copilot-instructions.yml b/.github/workflows/check-copilot-instructions.yml new file mode 100644 index 0000000..9a06155 --- /dev/null +++ b/.github/workflows/check-copilot-instructions.yml @@ -0,0 +1,118 @@ +name: Check Copilot Instructions Sync + +on: + push: + branches: '*' + pull_request: + branches: '*' + +jobs: + check-copilot-instructions: + runs-on: ubuntu-latest + + steps: + - name: Checkout current repository + uses: actions/checkout@v4 + + - name: Download copilot-instructions.md from flipDevTools + id: download-source + run: | + echo "Downloading copilot-instructions.md from flipDevTools..." + + # Try multiple possible paths for the copilot instructions + POSSIBLE_PATHS=( + ".github/copilot-instructions.md" + "copilot-instructions.md" + ".github/copilot_instructions.md" + "docs/copilot-instructions.md" + ) + + DOWNLOADED=false + for path in "${POSSIBLE_PATHS[@]}"; do + echo "Trying path: $path" + if curl -s -H "Authorization: token ${{ secrets.TOKEN }}" \ + -H "Accept: application/vnd.github.v3.raw" \ + -o /tmp/source-copilot-instructions.md \ + "https://api.github.com/repos/Displayr/flipDevTools/contents/$path" 2>/dev/null; then + + # Check if we got actual content (not an error response) + if [ -f /tmp/source-copilot-instructions.md ] && [ -s /tmp/source-copilot-instructions.md ]; then + # Verify it's not a JSON error response + if ! grep -q '"message".*"Not Found"' /tmp/source-copilot-instructions.md; then + echo "✅ Successfully downloaded from: $path" + echo "source_path=$path" >> $GITHUB_OUTPUT + DOWNLOADED=true + break + fi + fi + fi + done + + if [ "$DOWNLOADED" = false ]; then + echo "❌ Could not find copilot-instructions.md in flipDevTools repo" + echo "This may indicate the file doesn't exist or has been moved." + echo "Please check the flipDevTools repository structure." + exit 1 + fi + + - name: Check if local copilot-instructions.md exists + id: check-local + run: | + if [ ! -f .github/copilot-instructions.md ]; then + echo "❌ No copilot-instructions.md found in this repository" + echo "Expected location: .github/copilot-instructions.md" + echo "exists=false" >> $GITHUB_OUTPUT + exit 1 + else + echo "✅ Found local copilot-instructions.md" + echo "exists=true" >> $GITHUB_OUTPUT + fi + + - name: Compare files + run: | + echo "Comparing copilot-instructions.md files..." + echo "Source: flipDevTools/${{ steps.download-source.outputs.source_path }}" + echo "Local: .github/copilot-instructions.md" + echo "" + + # Compare the files + if diff -u /tmp/source-copilot-instructions.md .github/copilot-instructions.md > /tmp/diff_output; then + echo "✅ Files match perfectly!" + echo "Your copilot-instructions.md is up to date with flipDevTools." + else + echo "❌ Files do not match!" + echo "" + echo "Differences found:" + echo "==================" + cat /tmp/diff_output + echo "==================" + echo "" + echo "To fix this issue:" + echo "1. Update your .github/copilot-instructions.md to match the source" + echo "2. Or run the update-copilot-instructions workflow" + echo "3. Or manually sync the files" + echo "" + echo "Source file location: flipDevTools/${{ steps.download-source.outputs.source_path }}" + exit 1 + fi + + - name: Verify file integrity + run: | + echo "Verifying file integrity..." + + # Check that the local file is not empty + if [ ! -s .github/copilot-instructions.md ]; then + echo "❌ Local copilot-instructions.md is empty" + exit 1 + fi + + # Check that it contains expected content patterns + if ! grep -q -i "copilot\|instruction\|coding\|standard" .github/copilot-instructions.md; then + echo "⚠️ Warning: File doesn't seem to contain typical copilot instruction content" + echo "Please verify the file contains the expected coding standards and instructions" + else + echo "✅ File appears to contain valid copilot instructions" + fi + + echo "File size: $(wc -c < .github/copilot-instructions.md) bytes" + echo "Line count: $(wc -l < .github/copilot-instructions.md) lines" \ No newline at end of file From 36df9de258d88374868b9b960e1420f97d8b3efd Mon Sep 17 00:00:00 2001 From: Justin Yap Date: Fri, 3 Oct 2025 11:03:30 +1000 Subject: [PATCH 02/16] Create copilot-instructions.md --- .github/copilot-instructions.md | 226 ++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 .github/copilot-instructions.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..9a6a586 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,226 @@ +# Copilot Instructions for flipData + +This document provides coding standards and best practices for the flipData R package development. + +## General R Coding Standards + +### Assignment Operators +- **ALWAYS use `<-` for assignment, never `=`** +- Function parameters should use `=` (this is correct R syntax) +- Examples: + ```r + # Correct + my_variable <- some_function(param = value) + + # Incorrect + my_variable = some_function(param = value) + ``` + +### String Quotes +- **Use double quotes `"` for strings, avoid single quotes `'`** +- Exception: Single quotes are acceptable within double-quoted strings +- Examples: + ```r + # Correct + message <- "This is a string" + pattern <- "Can't use single quotes here" + + # Incorrect + message <- 'This is a string' + ``` + +### Line Length +- **Maximum line length: 120 characters** +- Break long lines using appropriate indentation +- Function calls with many parameters should be broken across lines: + ```r + # Correct + result <- some_long_function_name( + parameter_one = value1, + parameter_two = value2, + parameter_three = value3 + ) + + # Also correct for long expressions + long_message <- paste0("This is a very long message that exceeds ", + "the line length limit and should be broken ", + "across multiple lines") + ``` + +### Naming Conventions +- **Variables and functions**: Use `snake_case` or `dotted.case` (prefer `dotted.case` for parameters) +- **Constants**: Use `UPPER_CASE` +- **Private functions**: Prefix with `.` (e.g., `.private_function`) + +### Indentation and Spacing +- **Use 4 spaces for indentation, never tabs** +- Add spaces around operators (`<-`, `=`, `+`, `-`, etc.) +- No trailing whitespace + +## flipData Package Specific Guidelines + +### Error Handling +- **Use `flipU::StopForUserError()` for user-facing errors** +- Include clear, actionable error messages +- Example: + ```r + if (length(data) == 0) { + StopForUserError("No data provided. Please supply a valid dataset.") + } + ``` + +### Dependencies +- **Import functions explicitly using `@importFrom`** +- Common imports for flipData: + ```r + #' @importFrom flipU StopForUserError + #' @importFrom flipAPI QLoadData + #' @importFrom haven read_sav + ``` + +### Data Handling +- **Preserve SPSS metadata** when working with .sav files +- Use `attr()` to maintain variable labels and value labels +- Handle missing data appropriately + +### Function Documentation +- **All exported functions MUST have complete roxygen2 documentation** +- Include `@param` for all parameters +- Include `@return` describing the return value +- Include `@export` for exported functions +- Use `@noRd` for internal functions +- Example: + ```r + #' Merge multiple SPSS data sets + #' + #' @param data.set.names A character vector of data set names + #' @param min.data.sets Minimum number of data sets required + #' @return A list of data frames + #' @export + #' @importFrom flipU StopForUserError + ``` + +### SPSS Integration +- **Variable names**: Ensure compatibility with SPSS naming restrictions +- **Reserved keywords**: Handle SPSS reserved words appropriately +- **File handling**: Use proper error handling for file I/O operations + +## Code Quality Standards + +### Functions +- **Keep functions focused** - one responsibility per function +- **Use descriptive names** that clearly indicate purpose +- **Validate inputs** at the beginning of functions +- **Return consistent types** + +### Comments +- **Use `#` for single-line comments** +- **Explain the "why", not the "what"** +- **Document complex algorithms or business logic** +- **Keep comments up-to-date with code changes** + +### Testing +- **Write unit tests** for all exported functions +- **Use `testthat` framework** +- **Test edge cases and error conditions** +- **Maintain high test coverage** + +## File Organization + +### R Files +- **One main function per file** when possible +- **Group related utility functions** together +- **Use clear, descriptive file names** + +### Documentation +- **Keep man/ directory up-to-date** with roxygen2 +- **Update NAMESPACE automatically** with roxygen2 +- **Maintain comprehensive vignettes** for complex functionality + +## Git and Version Control + +### Commit Messages +- **Use descriptive commit messages** +- **Start with verb in present tense** (e.g., "Add", "Fix", "Update") +- **Reference issues when applicable** + +### Branching +- **Use feature branches** for development +- **Keep branches focused** on single features or fixes +- **Delete merged branches** to keep repository clean + +## Performance Considerations + +### Memory Usage +- **Avoid unnecessary data copying** +- **Use appropriate data structures** +- **Consider memory-efficient alternatives** for large datasets + +### Computational Efficiency +- **Vectorize operations** when possible +- **Avoid loops** when vectorized alternatives exist +- **Profile code** for performance bottlenecks + +## Security and Privacy + +### Data Handling +- **Never commit sensitive data** to version control +- **Use appropriate file permissions** +- **Handle user data responsibly** + +## Package Maintenance + +### Dependencies +- **Minimize external dependencies** +- **Pin version ranges** for critical dependencies +- **Regularly update dependencies** for security patches + +### Documentation +- **Keep README.md current** +- **Update NEWS.md** for each release +- **Maintain clear installation instructions** + +## Example Code Patterns + +### Typical Function Structure +```r +#' Function title +#' +#' @param data A data frame +#' @param subset Optional subset condition +#' @return Processed data frame +#' @export +#' @importFrom flipU StopForUserError +myFunction <- function(data, subset = NULL) { + # Validate inputs + if (missing(data) || !is.data.frame(data)) { + StopForUserError("Data must be a data frame") + } + + # Process data + result <- processData(data, subset) + + # Return result + result +} +``` + +### Error Handling Pattern +```r +# Check for required conditions +if (condition_not_met) { + StopForUserError("Clear description of what went wrong and how to fix it") +} +``` + +### SPSS Integration Pattern +```r +# Preserve SPSS attributes +original_attrs <- attributes(data) +data <- process_data(data) +attributes(data) <- original_attrs +``` + +--- + +These instructions ensure code quality, maintainability, and consistency across the flipData package. Always prioritize clarity and user experience in your implementations. \ No newline at end of file From 362af12edd26e2e5284e9ebcc2ea1876ad9ec116 Mon Sep 17 00:00:00 2001 From: Justin Yap Date: Fri, 3 Oct 2025 11:05:34 +1000 Subject: [PATCH 03/16] Only on PR --- .github/workflows/check-copilot-instructions.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/check-copilot-instructions.yml b/.github/workflows/check-copilot-instructions.yml index 9a06155..59fef5b 100644 --- a/.github/workflows/check-copilot-instructions.yml +++ b/.github/workflows/check-copilot-instructions.yml @@ -1,8 +1,6 @@ name: Check Copilot Instructions Sync on: - push: - branches: '*' pull_request: branches: '*' From fc4ee5b19802f4a03a77777e26f6ff51eea4f6af Mon Sep 17 00:00:00 2001 From: Justin Yap Date: Fri, 3 Oct 2025 11:22:49 +1000 Subject: [PATCH 04/16] Update check-copilot-instructions.yml --- .github/workflows/check-copilot-instructions.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/check-copilot-instructions.yml b/.github/workflows/check-copilot-instructions.yml index 59fef5b..1bc49cb 100644 --- a/.github/workflows/check-copilot-instructions.yml +++ b/.github/workflows/check-copilot-instructions.yml @@ -28,8 +28,7 @@ jobs: DOWNLOADED=false for path in "${POSSIBLE_PATHS[@]}"; do echo "Trying path: $path" - if curl -s -H "Authorization: token ${{ secrets.TOKEN }}" \ - -H "Accept: application/vnd.github.v3.raw" \ + if curl -s -H "Accept: application/vnd.github.v3.raw" \ -o /tmp/source-copilot-instructions.md \ "https://api.github.com/repos/Displayr/flipDevTools/contents/$path" 2>/dev/null; then From 0a0e4dc751e68143cf5aa1b8c7ea538230bbd806 Mon Sep 17 00:00:00 2001 From: Justin Yap Date: Fri, 3 Oct 2025 11:28:29 +1000 Subject: [PATCH 05/16] flipU --- .github/workflows/check-copilot-instructions.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/check-copilot-instructions.yml b/.github/workflows/check-copilot-instructions.yml index 1bc49cb..91859df 100644 --- a/.github/workflows/check-copilot-instructions.yml +++ b/.github/workflows/check-copilot-instructions.yml @@ -12,10 +12,10 @@ jobs: - name: Checkout current repository uses: actions/checkout@v4 - - name: Download copilot-instructions.md from flipDevTools + - name: Download copilot-instructions.md from flipU id: download-source run: | - echo "Downloading copilot-instructions.md from flipDevTools..." + echo "Downloading copilot-instructions.md from flipU..." # Try multiple possible paths for the copilot instructions POSSIBLE_PATHS=( @@ -30,7 +30,7 @@ jobs: echo "Trying path: $path" if curl -s -H "Accept: application/vnd.github.v3.raw" \ -o /tmp/source-copilot-instructions.md \ - "https://api.github.com/repos/Displayr/flipDevTools/contents/$path" 2>/dev/null; then + "https://api.github.com/repos/Displayr/flipU/contents/$path" 2>/dev/null; then # Check if we got actual content (not an error response) if [ -f /tmp/source-copilot-instructions.md ] && [ -s /tmp/source-copilot-instructions.md ]; then @@ -46,9 +46,9 @@ jobs: done if [ "$DOWNLOADED" = false ]; then - echo "❌ Could not find copilot-instructions.md in flipDevTools repo" + echo "❌ Could not find copilot-instructions.md in flipU repo" echo "This may indicate the file doesn't exist or has been moved." - echo "Please check the flipDevTools repository structure." + echo "Please check the flipU repository structure." exit 1 fi @@ -68,14 +68,14 @@ jobs: - name: Compare files run: | echo "Comparing copilot-instructions.md files..." - echo "Source: flipDevTools/${{ steps.download-source.outputs.source_path }}" + echo "Source: flipU/${{ steps.download-source.outputs.source_path }}" echo "Local: .github/copilot-instructions.md" echo "" # Compare the files if diff -u /tmp/source-copilot-instructions.md .github/copilot-instructions.md > /tmp/diff_output; then echo "✅ Files match perfectly!" - echo "Your copilot-instructions.md is up to date with flipDevTools." + echo "Your copilot-instructions.md is up to date with flipU." else echo "❌ Files do not match!" echo "" @@ -89,7 +89,7 @@ jobs: echo "2. Or run the update-copilot-instructions workflow" echo "3. Or manually sync the files" echo "" - echo "Source file location: flipDevTools/${{ steps.download-source.outputs.source_path }}" + echo "Source file location: flipU/${{ steps.download-source.outputs.source_path }}" exit 1 fi From 4cbeb42ca3c316888509fe6f09e544764b58b6e6 Mon Sep 17 00:00:00 2001 From: jrwishart Date: Fri, 3 Oct 2025 11:42:08 +1000 Subject: [PATCH 06/16] Use flipU instructions for merge --- .github/copilot-instructions.md | 318 ++++++++++---------------------- 1 file changed, 93 insertions(+), 225 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 9a6a586..16819b3 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,226 +1,94 @@ -# Copilot Instructions for flipData - -This document provides coding standards and best practices for the flipData R package development. - -## General R Coding Standards - -### Assignment Operators -- **ALWAYS use `<-` for assignment, never `=`** -- Function parameters should use `=` (this is correct R syntax) -- Examples: - ```r - # Correct - my_variable <- some_function(param = value) - - # Incorrect - my_variable = some_function(param = value) - ``` - -### String Quotes -- **Use double quotes `"` for strings, avoid single quotes `'`** -- Exception: Single quotes are acceptable within double-quoted strings -- Examples: - ```r - # Correct - message <- "This is a string" - pattern <- "Can't use single quotes here" - - # Incorrect - message <- 'This is a string' - ``` - -### Line Length -- **Maximum line length: 120 characters** -- Break long lines using appropriate indentation -- Function calls with many parameters should be broken across lines: - ```r - # Correct - result <- some_long_function_name( - parameter_one = value1, - parameter_two = value2, - parameter_three = value3 - ) - - # Also correct for long expressions - long_message <- paste0("This is a very long message that exceeds ", - "the line length limit and should be broken ", - "across multiple lines") - ``` - -### Naming Conventions -- **Variables and functions**: Use `snake_case` or `dotted.case` (prefer `dotted.case` for parameters) -- **Constants**: Use `UPPER_CASE` -- **Private functions**: Prefix with `.` (e.g., `.private_function`) - -### Indentation and Spacing -- **Use 4 spaces for indentation, never tabs** -- Add spaces around operators (`<-`, `=`, `+`, `-`, etc.) -- No trailing whitespace - -## flipData Package Specific Guidelines - -### Error Handling -- **Use `flipU::StopForUserError()` for user-facing errors** -- Include clear, actionable error messages -- Example: - ```r - if (length(data) == 0) { - StopForUserError("No data provided. Please supply a valid dataset.") - } - ``` - -### Dependencies -- **Import functions explicitly using `@importFrom`** -- Common imports for flipData: - ```r - #' @importFrom flipU StopForUserError - #' @importFrom flipAPI QLoadData - #' @importFrom haven read_sav - ``` - -### Data Handling -- **Preserve SPSS metadata** when working with .sav files -- Use `attr()` to maintain variable labels and value labels -- Handle missing data appropriately - -### Function Documentation -- **All exported functions MUST have complete roxygen2 documentation** -- Include `@param` for all parameters -- Include `@return` describing the return value -- Include `@export` for exported functions -- Use `@noRd` for internal functions -- Example: - ```r - #' Merge multiple SPSS data sets - #' - #' @param data.set.names A character vector of data set names - #' @param min.data.sets Minimum number of data sets required - #' @return A list of data frames - #' @export - #' @importFrom flipU StopForUserError - ``` - -### SPSS Integration -- **Variable names**: Ensure compatibility with SPSS naming restrictions -- **Reserved keywords**: Handle SPSS reserved words appropriately -- **File handling**: Use proper error handling for file I/O operations - -## Code Quality Standards - -### Functions -- **Keep functions focused** - one responsibility per function -- **Use descriptive names** that clearly indicate purpose -- **Validate inputs** at the beginning of functions -- **Return consistent types** - -### Comments -- **Use `#` for single-line comments** -- **Explain the "why", not the "what"** -- **Document complex algorithms or business logic** -- **Keep comments up-to-date with code changes** - -### Testing -- **Write unit tests** for all exported functions -- **Use `testthat` framework** -- **Test edge cases and error conditions** -- **Maintain high test coverage** - -## File Organization - -### R Files -- **One main function per file** when possible -- **Group related utility functions** together -- **Use clear, descriptive file names** - -### Documentation -- **Keep man/ directory up-to-date** with roxygen2 -- **Update NAMESPACE automatically** with roxygen2 -- **Maintain comprehensive vignettes** for complex functionality - -## Git and Version Control - -### Commit Messages -- **Use descriptive commit messages** -- **Start with verb in present tense** (e.g., "Add", "Fix", "Update") -- **Reference issues when applicable** - -### Branching -- **Use feature branches** for development -- **Keep branches focused** on single features or fixes -- **Delete merged branches** to keep repository clean - -## Performance Considerations - -### Memory Usage -- **Avoid unnecessary data copying** -- **Use appropriate data structures** -- **Consider memory-efficient alternatives** for large datasets - -### Computational Efficiency -- **Vectorize operations** when possible -- **Avoid loops** when vectorized alternatives exist -- **Profile code** for performance bottlenecks - -## Security and Privacy - -### Data Handling -- **Never commit sensitive data** to version control -- **Use appropriate file permissions** -- **Handle user data responsibly** - -## Package Maintenance - -### Dependencies -- **Minimize external dependencies** -- **Pin version ranges** for critical dependencies -- **Regularly update dependencies** for security patches - -### Documentation -- **Keep README.md current** -- **Update NEWS.md** for each release -- **Maintain clear installation instructions** - -## Example Code Patterns - -### Typical Function Structure -```r -#' Function title -#' -#' @param data A data frame -#' @param subset Optional subset condition -#' @return Processed data frame -#' @export -#' @importFrom flipU StopForUserError -myFunction <- function(data, subset = NULL) { - # Validate inputs - if (missing(data) || !is.data.frame(data)) { - StopForUserError("Data must be a data frame") +## Code Review Guidelines + +### R Package Standards +- This is a standard R package - all changes must maintain CRAN-compatible structure +- NAMESPACE is auto-generated by roxygen2 - never edit it directly +- DESCRIPTION must be kept valid with proper versioning +- All exported functions require complete roxygen2 documentation + +### Code Style Requirements +- **Naming conventions**: Use `dotted.case`, `camelCase`, or `PascalCase` consistently + - Parameters/variables: `dotted.case` (e.g., `response.format`, `text.variables`, `api.key`) + - Functions: `camelCase` or `PascalCase` or `.camelCase` (e.g., `checkInputs`, `MakeOutput`, or `.nestedHelper`) + - Use `PascalCase` for exported functions (e.g., `AddFormulaBars`, `RegressionTable`) + - Use `camelCase` for internal/helper functions (e.g., `checkInputs`) + - Use `.camelCase` for internal nested functions + e.g., within an internal function + ``` + addOneToAll <- function(x) { + .helpAdd <- function(y) { + y + 1 + } + vapply(x, .helpAdd, numeric(1L) } - - # Process data - result <- processData(data, subset) - - # Return result - result -} -``` - -### Error Handling Pattern -```r -# Check for required conditions -if (condition_not_met) { - StopForUserError("Clear description of what went wrong and how to fix it") -} -``` - -### SPSS Integration Pattern -```r -# Preserve SPSS attributes -original_attrs <- attributes(data) -data <- process_data(data) -attributes(data) <- original_attrs -``` - ---- - -These instructions ensure code quality, maintainability, and consistency across the flipData package. Always prioritize clarity and user experience in your implementations. \ No newline at end of file + ``` +- **Object name length**: Maximum 50 characters +- **Assignment**: Always use `<-` for assignment, never `=` +- **Pipes**: Use native pipe `|>` for chaining operations +- **NULL coalescing**: Use `%||%` operator for NULL defaults +- **Indentation**: 4 spaces +- **Line length**: Maximum 120 characters +- **No trailing whitespace** +- **Consistent quotes**: Always use double quotes `"` for strings. It is ok for quotes within strings to be single quotes `'` but the parent string must use double quotes. +- **Prefer full words over abbreviations**: e.g., `response.format` over `resp.fmt` +- **Function names**: Use descriptive names that clearly indicate purpose: e.g. `createSummaryTableForRegressionResults()` rather than `make()` +- **Braces**: Always use braces `{}` for functions, `if`, `else if` and `else` blocks. Except for the case of a single line statements. In particular, use Kernighan & Ritchie style braces. + - e.g. The following is acceptable: + ``` + y <- if (x > 0) x else -x + w <- if (condition) { + z <- computeSomething(x) + foo(z) + } else { + z <- computeSomethingElse(x) + bar(z) + } + ``` +- **Redundant return**: Avoid using `return()` unless exiting early from a function. The last evaluated expression is returned by default. + +### Function Design Patterns +- **Error handling**: Use `flipU::StopForUserError()` for user-facing errors with clear, actionable messages +- **Return values**: Functions used for validation/side effects should explicitly return `NULL` +- **Internal functions**: Internal or helper functions should not be exported; use `@noRd` in roxygen comments +- **File organization**: Group related functions into logical files (e.g., check.inputs.R, tidy.inputs.R) +- **Importing functions**: Use `@importFrom` in roxygen comments for all external package functions used and avoid usage of `:::`. +- **Type checking**: Don't use `sapply`. Use `vapply` with a specified return type for type safety. +- **Formatting numbers for printing**: Use `flipFormat::FormatAsReal()` and `flipFormat::FormatAsPercent()` instead of base R formatting functions +- **Calculations**: Use the following functions where possible: + - `verbs::Average` instead of `mean` + - `verbs::Sum` instead of `sum` + - `verbs::Min` instead of `min` + - `verbs::Max` instead of `max` + - `verbs::Variance` instead of `var` + - `verbs::StandardDeviation` instead of `sd` + +### Documentation Requirements +- All exported functions must have complete roxygen2 documentation +- Required tags: `@param` (for each parameter), `@return`, `@export` +- Include `@importFrom` for all external package functions used +- Optional but recommended: `@details`, `@examples` + +### Testing Requirements +- Use testthat v3 framework (edition 3) +- Test files must be in `tests/testthat/` with `test-` prefix +- Include snapshot tests where appropriate (`_snaps/` directory) + +### Security & Best Practices +- **Never log or expose API keys or secrets** + +## PR Review Focus Areas +1. **Breaking changes**: Flag any changes to exported function signatures +2. **Documentation**: Ensure all new/modified exports have complete roxygen2 docs +3. **Testing**: Verify new functionality has corresponding tests +4. **Style consistency**: Check adherence to naming convetions, `<-`, `|>` patterns +5. **Error messages**: Ensure user-facing errors are clear and helpful +6. **Line length**: Flag lines exceeding 120 characters +7. **Object names**: Ensure names don't exceed 50 characters + +## Common Issues to Flag +- Using `=` instead of `<-` for assignment +- Missing or incomplete roxygen2 documentation +- Direct API key exposure or logging +- Inconsistent naming conventions (mixing dotted.case/camelCase inappropriately) +- New dependencies without justification +- Error messages that don't guide users to solutions From a012c1390c7bbbfcb76e0ff88da4a844899e67b9 Mon Sep 17 00:00:00 2001 From: jrwishart Date: Fri, 3 Oct 2025 11:49:17 +1000 Subject: [PATCH 07/16] Add .github to .Rbuildignore --- .Rbuildignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.Rbuildignore b/.Rbuildignore index 7856c9b..5234e54 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -2,3 +2,4 @@ ^\.Rproj\.user$ .*~ ^\.circleci/config\.yml$ +.github From aa2a138e40c6c92348e9131b086f7aa6d9e36926 Mon Sep 17 00:00:00 2001 From: Justin Yap Date: Fri, 3 Oct 2025 11:50:57 +1000 Subject: [PATCH 08/16] Add script --- scripts/update-copilot-instructions.sh | 130 +++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 scripts/update-copilot-instructions.sh diff --git a/scripts/update-copilot-instructions.sh b/scripts/update-copilot-instructions.sh new file mode 100644 index 0000000..5a023dc --- /dev/null +++ b/scripts/update-copilot-instructions.sh @@ -0,0 +1,130 @@ +#!/bin/bash + +# Script to update copilot-instructions.md from flipU repository +# Usage: ./update-copilot-instructions.sh + +set -e # Exit on any error + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Function to print colored output +print_status() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +print_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Check if we're in a git repository +if [ ! -d ".git" ]; then + print_error "This script must be run from the root of a git repository" + exit 1 +fi + +# Create .github directory if it doesn't exist +if [ ! -d ".github" ]; then + print_status "Creating .github directory..." + mkdir -p .github +fi + +# Try multiple possible paths for the copilot instructions +POSSIBLE_PATHS=( + ".github/copilot-instructions.md" + "copilot-instructions.md" + ".github/copilot_instructions.md" + "docs/copilot-instructions.md" + ".github/copilot-instructions.md" +) + +print_status "Searching for copilot-instructions.md in flipU repository..." + +DOWNLOADED=false +for path in "${POSSIBLE_PATHS[@]}"; do + print_status "Trying path: $path" + + HTTP_CODE=$(curl -s -w "%{http_code}" \ + -H "Accept: application/vnd.github.v3.raw" \ + -o "/tmp/copilot-instructions-temp.md" \ + "https://api.github.com/repos/Displayr/flipU/contents/$path" 2>/dev/null || echo "000") + + if [ "$HTTP_CODE" = "200" ]; then + # Check if we got actual content (not an error response) + if [ -f "/tmp/copilot-instructions-temp.md" ] && [ -s "/tmp/copilot-instructions-temp.md" ]; then + # Verify it's not a JSON error response + if ! grep -q '"message".*"Not Found"' "/tmp/copilot-instructions-temp.md" 2>/dev/null; then + print_success "Successfully downloaded from: $path" + mv "/tmp/copilot-instructions-temp.md" ".github/copilot-instructions.md" + DOWNLOADED=true + SOURCE_PATH=$path + break + fi + fi + elif [ "$HTTP_CODE" = "404" ]; then + print_status "File not found at: $path" + else + print_warning "HTTP $HTTP_CODE when accessing: $path" + fi +done + +# Clean up temp file +rm -f "/tmp/copilot-instructions-temp.md" + +if [ "$DOWNLOADED" = false ]; then + print_error "Could not find copilot-instructions.md in flipU repository" + print_error "Checked paths: ${POSSIBLE_PATHS[*]}" + + # Try to list available files for debugging + print_status "Attempting to list available files in flipU..." + curl -s "https://api.github.com/repos/Displayr/flipU/contents" | \ + grep '"name"' | head -10 || print_warning "Could not list repository contents" + + exit 1 +fi + +# Verify the downloaded file +if [ ! -s ".github/copilot-instructions.md" ]; then + print_error "Downloaded file is empty" + exit 1 +fi + +# Check if it looks like a valid copilot instructions file +if ! grep -q -i "copilot\|instruction\|coding\|standard" ".github/copilot-instructions.md"; then + print_warning "Downloaded file may not contain typical copilot instruction content" + print_warning "Please verify the content manually" +fi + +# Show file information +FILE_SIZE=$(wc -c < ".github/copilot-instructions.md") +LINE_COUNT=$(wc -l < ".github/copilot-instructions.md") + +print_success "File updated successfully!" +print_status "Source: flipU/$SOURCE_PATH" +print_status "Local: .github/copilot-instructions.md" +print_status "Size: $FILE_SIZE bytes" +print_status "Lines: $LINE_COUNT" + +# Check git status for informational purposes only +if command -v git >/dev/null 2>&1; then + if git diff --quiet .github/copilot-instructions.md 2>/dev/null; then + print_status "No changes detected in copilot-instructions.md" + else + print_status "Changes detected in copilot-instructions.md" + print_status "File updated" + fi +fi + +print_success "Update completed successfully!" \ No newline at end of file From 0ed23dfa1353f46a184e49873e50c3729c55ad09 Mon Sep 17 00:00:00 2001 From: jrwishart Date: Fri, 3 Oct 2025 12:04:57 +1000 Subject: [PATCH 09/16] Use variables to define filenames --- scripts/update-copilot-instructions.sh | 34 ++++++++++++++------------ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/scripts/update-copilot-instructions.sh b/scripts/update-copilot-instructions.sh index 5a023dc..d091e30 100644 --- a/scripts/update-copilot-instructions.sh +++ b/scripts/update-copilot-instructions.sh @@ -47,27 +47,29 @@ POSSIBLE_PATHS=( "copilot-instructions.md" ".github/copilot_instructions.md" "docs/copilot-instructions.md" - ".github/copilot-instructions.md" ) +TEMP_FILE="/tmp/copilot-instructions-temp.md" +DESIRED_FILE=".github/copilot-instructions.md" + print_status "Searching for copilot-instructions.md in flipU repository..." DOWNLOADED=false for path in "${POSSIBLE_PATHS[@]}"; do print_status "Trying path: $path" - + HTTP_CODE=$(curl -s -w "%{http_code}" \ -H "Accept: application/vnd.github.v3.raw" \ -o "/tmp/copilot-instructions-temp.md" \ "https://api.github.com/repos/Displayr/flipU/contents/$path" 2>/dev/null || echo "000") - + if [ "$HTTP_CODE" = "200" ]; then # Check if we got actual content (not an error response) if [ -f "/tmp/copilot-instructions-temp.md" ] && [ -s "/tmp/copilot-instructions-temp.md" ]; then # Verify it's not a JSON error response if ! grep -q '"message".*"Not Found"' "/tmp/copilot-instructions-temp.md" 2>/dev/null; then print_success "Successfully downloaded from: $path" - mv "/tmp/copilot-instructions-temp.md" ".github/copilot-instructions.md" + mv $TEMP_FILE $DESIRED_FILE DOWNLOADED=true SOURCE_PATH=$path break @@ -81,50 +83,50 @@ for path in "${POSSIBLE_PATHS[@]}"; do done # Clean up temp file -rm -f "/tmp/copilot-instructions-temp.md" +rm -f $TEMP_FILE if [ "$DOWNLOADED" = false ]; then print_error "Could not find copilot-instructions.md in flipU repository" print_error "Checked paths: ${POSSIBLE_PATHS[*]}" - + # Try to list available files for debugging print_status "Attempting to list available files in flipU..." curl -s "https://api.github.com/repos/Displayr/flipU/contents" | \ grep '"name"' | head -10 || print_warning "Could not list repository contents" - + exit 1 fi # Verify the downloaded file -if [ ! -s ".github/copilot-instructions.md" ]; then +if [ ! -s $DESIRED_FILE ]; then print_error "Downloaded file is empty" exit 1 fi # Check if it looks like a valid copilot instructions file -if ! grep -q -i "copilot\|instruction\|coding\|standard" ".github/copilot-instructions.md"; then +if ! grep -q -i "copilot\|instruction\|coding\|standard" $DESIRED_FILE; then print_warning "Downloaded file may not contain typical copilot instruction content" print_warning "Please verify the content manually" fi # Show file information -FILE_SIZE=$(wc -c < ".github/copilot-instructions.md") -LINE_COUNT=$(wc -l < ".github/copilot-instructions.md") +FILE_SIZE=$(wc -c < $DESIRED_FILE) +LINE_COUNT=$(wc -l < $DESIRED_FILE) print_success "File updated successfully!" print_status "Source: flipU/$SOURCE_PATH" -print_status "Local: .github/copilot-instructions.md" +print_status "Local: $DESIRED_FILE" print_status "Size: $FILE_SIZE bytes" print_status "Lines: $LINE_COUNT" # Check git status for informational purposes only if command -v git >/dev/null 2>&1; then - if git diff --quiet .github/copilot-instructions.md 2>/dev/null; then - print_status "No changes detected in copilot-instructions.md" + if git diff --quiet $DESIRED_FILE 2>/dev/null; then + print_status "No changes detected in ${DESIRED_FILE}" else - print_status "Changes detected in copilot-instructions.md" + print_status "Changes detected in ${DESIRED_FILE}" print_status "File updated" fi fi -print_success "Update completed successfully!" \ No newline at end of file +print_success "Update completed successfully!" From fa3ef255023bdb38062987aea7af27c5a1f729b8 Mon Sep 17 00:00:00 2001 From: jrwishart Date: Fri, 3 Oct 2025 12:29:57 +1000 Subject: [PATCH 10/16] Update instructions to user for script --- scripts/update-copilot-instructions.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/update-copilot-instructions.sh b/scripts/update-copilot-instructions.sh index d091e30..82273bf 100644 --- a/scripts/update-copilot-instructions.sh +++ b/scripts/update-copilot-instructions.sh @@ -1,7 +1,9 @@ #!/bin/bash # Script to update copilot-instructions.md from flipU repository -# Usage: ./update-copilot-instructions.sh +# Usage: ./scripts/update-copilot-instructions.sh +# Note: This script should be run from the root of this repository +# and requires internet access with curl installed. set -e # Exit on any error From c3a65999fb86897ed88756562c6f510e9e0bd842 Mon Sep 17 00:00:00 2001 From: jrwishart Date: Fri, 3 Oct 2025 12:31:45 +1000 Subject: [PATCH 11/16] Make script executable --- scripts/update-copilot-instructions.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 scripts/update-copilot-instructions.sh diff --git a/scripts/update-copilot-instructions.sh b/scripts/update-copilot-instructions.sh old mode 100644 new mode 100755 From 6d4452b13ca1f58805c8a03dcbb5e305d4af6a21 Mon Sep 17 00:00:00 2001 From: jrwishart Date: Fri, 3 Oct 2025 12:34:13 +1000 Subject: [PATCH 12/16] move script to .github directory and update feedback in workflow --- .../update-copilot-instructions.sh | 0 .../workflows/check-copilot-instructions.yml | 30 +++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) rename {scripts => .github}/update-copilot-instructions.sh (100%) diff --git a/scripts/update-copilot-instructions.sh b/.github/update-copilot-instructions.sh similarity index 100% rename from scripts/update-copilot-instructions.sh rename to .github/update-copilot-instructions.sh diff --git a/.github/workflows/check-copilot-instructions.yml b/.github/workflows/check-copilot-instructions.yml index 91859df..ccdb9c0 100644 --- a/.github/workflows/check-copilot-instructions.yml +++ b/.github/workflows/check-copilot-instructions.yml @@ -7,16 +7,16 @@ on: jobs: check-copilot-instructions: runs-on: ubuntu-latest - + steps: - name: Checkout current repository uses: actions/checkout@v4 - + - name: Download copilot-instructions.md from flipU id: download-source run: | echo "Downloading copilot-instructions.md from flipU..." - + # Try multiple possible paths for the copilot instructions POSSIBLE_PATHS=( ".github/copilot-instructions.md" @@ -24,14 +24,14 @@ jobs: ".github/copilot_instructions.md" "docs/copilot-instructions.md" ) - + DOWNLOADED=false for path in "${POSSIBLE_PATHS[@]}"; do echo "Trying path: $path" if curl -s -H "Accept: application/vnd.github.v3.raw" \ -o /tmp/source-copilot-instructions.md \ "https://api.github.com/repos/Displayr/flipU/contents/$path" 2>/dev/null; then - + # Check if we got actual content (not an error response) if [ -f /tmp/source-copilot-instructions.md ] && [ -s /tmp/source-copilot-instructions.md ]; then # Verify it's not a JSON error response @@ -44,14 +44,14 @@ jobs: fi fi done - + if [ "$DOWNLOADED" = false ]; then echo "❌ Could not find copilot-instructions.md in flipU repo" echo "This may indicate the file doesn't exist or has been moved." echo "Please check the flipU repository structure." exit 1 fi - + - name: Check if local copilot-instructions.md exists id: check-local run: | @@ -64,14 +64,14 @@ jobs: echo "✅ Found local copilot-instructions.md" echo "exists=true" >> $GITHUB_OUTPUT fi - + - name: Compare files run: | echo "Comparing copilot-instructions.md files..." echo "Source: flipU/${{ steps.download-source.outputs.source_path }}" echo "Local: .github/copilot-instructions.md" echo "" - + # Compare the files if diff -u /tmp/source-copilot-instructions.md .github/copilot-instructions.md > /tmp/diff_output; then echo "✅ Files match perfectly!" @@ -86,23 +86,23 @@ jobs: echo "" echo "To fix this issue:" echo "1. Update your .github/copilot-instructions.md to match the source" - echo "2. Or run the update-copilot-instructions workflow" + echo "2. Or run the update-copilot-instructions.sh script in .github" echo "3. Or manually sync the files" echo "" echo "Source file location: flipU/${{ steps.download-source.outputs.source_path }}" exit 1 fi - + - name: Verify file integrity run: | echo "Verifying file integrity..." - + # Check that the local file is not empty if [ ! -s .github/copilot-instructions.md ]; then echo "❌ Local copilot-instructions.md is empty" exit 1 fi - + # Check that it contains expected content patterns if ! grep -q -i "copilot\|instruction\|coding\|standard" .github/copilot-instructions.md; then echo "⚠️ Warning: File doesn't seem to contain typical copilot instruction content" @@ -110,6 +110,6 @@ jobs: else echo "✅ File appears to contain valid copilot instructions" fi - + echo "File size: $(wc -c < .github/copilot-instructions.md) bytes" - echo "Line count: $(wc -l < .github/copilot-instructions.md) lines" \ No newline at end of file + echo "Line count: $(wc -l < .github/copilot-instructions.md) lines" From 432498794d427812a80ac05389357e9e0aaa38cc Mon Sep 17 00:00:00 2001 From: jrwishart Date: Fri, 3 Oct 2025 13:04:35 +1000 Subject: [PATCH 13/16] Update path in instructions for update script --- .github/update-copilot-instructions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/update-copilot-instructions.sh b/.github/update-copilot-instructions.sh index 82273bf..0b350c7 100755 --- a/.github/update-copilot-instructions.sh +++ b/.github/update-copilot-instructions.sh @@ -1,7 +1,7 @@ #!/bin/bash # Script to update copilot-instructions.md from flipU repository -# Usage: ./scripts/update-copilot-instructions.sh +# Usage: ./.github/update-copilot-instructions.sh # Note: This script should be run from the root of this repository # and requires internet access with curl installed. From faa2c43c2879f8936f92ab3e0509c96b3dd689c5 Mon Sep 17 00:00:00 2001 From: jrwishart Date: Fri, 3 Oct 2025 13:22:46 +1000 Subject: [PATCH 14/16] Update the feedback in workflow to get the script locally --- .github/workflows/check-copilot-instructions.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check-copilot-instructions.yml b/.github/workflows/check-copilot-instructions.yml index ccdb9c0..5516433 100644 --- a/.github/workflows/check-copilot-instructions.yml +++ b/.github/workflows/check-copilot-instructions.yml @@ -86,9 +86,10 @@ jobs: echo "" echo "To fix this issue:" echo "1. Update your .github/copilot-instructions.md to match the source" - echo "2. Or run the update-copilot-instructions.sh script in .github" - echo "3. Or manually sync the files" - echo "" + echo "2. Or run the shell script in flipU to do this for you." + echo " # Run these commands locally from the root of your repository" + echo " > curl -O -L https://raw.githubusercontent.com/Displayr/flipU/master/.github/update-copilot-instructions.sh" + echo " > bash update-copilot-instructions.sh" echo "Source file location: flipU/${{ steps.download-source.outputs.source_path }}" exit 1 fi From 4428a94d71ae536b7bb769c475b0d45369bafd5d Mon Sep 17 00:00:00 2001 From: jrwishart Date: Fri, 3 Oct 2025 13:25:55 +1000 Subject: [PATCH 15/16] Add git command suggestions too --- .github/workflows/check-copilot-instructions.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/check-copilot-instructions.yml b/.github/workflows/check-copilot-instructions.yml index 5516433..613da82 100644 --- a/.github/workflows/check-copilot-instructions.yml +++ b/.github/workflows/check-copilot-instructions.yml @@ -90,6 +90,9 @@ jobs: echo " # Run these commands locally from the root of your repository" echo " > curl -O -L https://raw.githubusercontent.com/Displayr/flipU/master/.github/update-copilot-instructions.sh" echo " > bash update-copilot-instructions.sh" + echo " > git add .github/copilot-instructions.md" + echo " > git commit -m 'Update copilot-instructions.md to match flipU'" + echo " > git push" echo "Source file location: flipU/${{ steps.download-source.outputs.source_path }}" exit 1 fi From e406eeeda33e391307d4977cf09c07eecf183128 Mon Sep 17 00:00:00 2001 From: jrwishart Date: Fri, 3 Oct 2025 13:31:36 +1000 Subject: [PATCH 16/16] Remove update script as it'll live in flipU --- .github/update-copilot-instructions.sh | 134 ------------------------- 1 file changed, 134 deletions(-) delete mode 100755 .github/update-copilot-instructions.sh diff --git a/.github/update-copilot-instructions.sh b/.github/update-copilot-instructions.sh deleted file mode 100755 index 0b350c7..0000000 --- a/.github/update-copilot-instructions.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/bin/bash - -# Script to update copilot-instructions.md from flipU repository -# Usage: ./.github/update-copilot-instructions.sh -# Note: This script should be run from the root of this repository -# and requires internet access with curl installed. - -set -e # Exit on any error - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Function to print colored output -print_status() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -print_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" -} - -print_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -print_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Check if we're in a git repository -if [ ! -d ".git" ]; then - print_error "This script must be run from the root of a git repository" - exit 1 -fi - -# Create .github directory if it doesn't exist -if [ ! -d ".github" ]; then - print_status "Creating .github directory..." - mkdir -p .github -fi - -# Try multiple possible paths for the copilot instructions -POSSIBLE_PATHS=( - ".github/copilot-instructions.md" - "copilot-instructions.md" - ".github/copilot_instructions.md" - "docs/copilot-instructions.md" -) - -TEMP_FILE="/tmp/copilot-instructions-temp.md" -DESIRED_FILE=".github/copilot-instructions.md" - -print_status "Searching for copilot-instructions.md in flipU repository..." - -DOWNLOADED=false -for path in "${POSSIBLE_PATHS[@]}"; do - print_status "Trying path: $path" - - HTTP_CODE=$(curl -s -w "%{http_code}" \ - -H "Accept: application/vnd.github.v3.raw" \ - -o "/tmp/copilot-instructions-temp.md" \ - "https://api.github.com/repos/Displayr/flipU/contents/$path" 2>/dev/null || echo "000") - - if [ "$HTTP_CODE" = "200" ]; then - # Check if we got actual content (not an error response) - if [ -f "/tmp/copilot-instructions-temp.md" ] && [ -s "/tmp/copilot-instructions-temp.md" ]; then - # Verify it's not a JSON error response - if ! grep -q '"message".*"Not Found"' "/tmp/copilot-instructions-temp.md" 2>/dev/null; then - print_success "Successfully downloaded from: $path" - mv $TEMP_FILE $DESIRED_FILE - DOWNLOADED=true - SOURCE_PATH=$path - break - fi - fi - elif [ "$HTTP_CODE" = "404" ]; then - print_status "File not found at: $path" - else - print_warning "HTTP $HTTP_CODE when accessing: $path" - fi -done - -# Clean up temp file -rm -f $TEMP_FILE - -if [ "$DOWNLOADED" = false ]; then - print_error "Could not find copilot-instructions.md in flipU repository" - print_error "Checked paths: ${POSSIBLE_PATHS[*]}" - - # Try to list available files for debugging - print_status "Attempting to list available files in flipU..." - curl -s "https://api.github.com/repos/Displayr/flipU/contents" | \ - grep '"name"' | head -10 || print_warning "Could not list repository contents" - - exit 1 -fi - -# Verify the downloaded file -if [ ! -s $DESIRED_FILE ]; then - print_error "Downloaded file is empty" - exit 1 -fi - -# Check if it looks like a valid copilot instructions file -if ! grep -q -i "copilot\|instruction\|coding\|standard" $DESIRED_FILE; then - print_warning "Downloaded file may not contain typical copilot instruction content" - print_warning "Please verify the content manually" -fi - -# Show file information -FILE_SIZE=$(wc -c < $DESIRED_FILE) -LINE_COUNT=$(wc -l < $DESIRED_FILE) - -print_success "File updated successfully!" -print_status "Source: flipU/$SOURCE_PATH" -print_status "Local: $DESIRED_FILE" -print_status "Size: $FILE_SIZE bytes" -print_status "Lines: $LINE_COUNT" - -# Check git status for informational purposes only -if command -v git >/dev/null 2>&1; then - if git diff --quiet $DESIRED_FILE 2>/dev/null; then - print_status "No changes detected in ${DESIRED_FILE}" - else - print_status "Changes detected in ${DESIRED_FILE}" - print_status "File updated" - fi -fi - -print_success "Update completed successfully!"