Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Documentation/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "documentation",
"version": "9.0.1",
"version": "9.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
Expand Down
2 changes: 1 addition & 1 deletion Extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "banglacode",
"displayName": "BanglaCode",
"description": "Language support for BanglaCode (.bang, .bangla, .bong) - Bengali Programming Language created by Ankan from West Bengal, India",
"version": "9.0.1",
"version": "9.1.0",
"publisher": "AnkanSaha",
"author": {
"name": "AnkanSaha"
Expand Down
38 changes: 38 additions & 0 deletions Scripts/install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,9 @@ Write-ColorOutput "[+] Latest Version: v$VERSION" "Green"
# Prepare download
$DOWNLOAD_FILE = "banglacode-windows-$ARCH.zip"
$DOWNLOAD_URL = "https://github.com/$REPO/releases/download/v$VERSION/$DOWNLOAD_FILE"
$CHECKSUM_URL = "https://github.com/$REPO/releases/download/v$VERSION/checksums.txt"
$TMP_FILE = Join-Path $env:TEMP $DOWNLOAD_FILE
$CHECKSUM_FILE = Join-Path $env:TEMP "checksums.txt"

Write-ColorOutput "[*] Downloading $DOWNLOAD_FILE..." "White"

Expand All @@ -249,6 +251,42 @@ if (-not (Download-File -Url $DOWNLOAD_URL -Destination $TMP_FILE)) {

Write-ColorOutput "[+] Download complete" "Green"

# Download checksums
Write-ColorOutput "[*] Verifying checksum..." "White"
if (-not (Download-File -Url $CHECKSUM_URL -Destination $CHECKSUM_FILE)) {
Write-ColorOutput "[X] Failed to download checksums" "Red"
Remove-Item $TMP_FILE -Force -ErrorAction SilentlyContinue
exit 1
}

# Parse expected checksum
$checksumContent = Get-Content $CHECKSUM_FILE
$expectedChecksum = ($checksumContent | Select-String -Pattern "$DOWNLOAD_FILE").Line -split '\s+' | Select-Object -First 1

if (-not $expectedChecksum) {
Write-ColorOutput "[X] Checksum not found for $DOWNLOAD_FILE" "Red"
Remove-Item $TMP_FILE, $CHECKSUM_FILE -Force -ErrorAction SilentlyContinue
exit 1
}

# Calculate actual checksum
$actualChecksum = (Get-FileHash -Path $TMP_FILE -Algorithm SHA256).Hash.ToLower()
$expectedChecksum = $expectedChecksum.ToLower()

if ($actualChecksum -ne $expectedChecksum) {
Write-ColorOutput "[X] Checksum verification failed!" "Red"
Write-ColorOutput " Expected: $expectedChecksum" "Red"
Write-ColorOutput " Got: $actualChecksum" "Red"
Write-ColorOutput " This may indicate a compromised download." "Red"
Remove-Item $TMP_FILE, $CHECKSUM_FILE -Force -ErrorAction SilentlyContinue
exit 1
}

Write-ColorOutput "[+] Checksum verified" "Green"

# Cleanup checksum file
Remove-Item $CHECKSUM_FILE -Force -ErrorAction SilentlyContinue

# Create install directory
Write-ColorOutput "[*] Installing to $INSTALL_DIR..." "White"

Expand Down
29 changes: 29 additions & 0 deletions Scripts/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,47 @@ else
fi

DOWNLOAD_URL="https://github.com/$REPO/releases/download/v$VERSION/$DOWNLOAD_FILE"
CHECKSUM_URL="https://github.com/$REPO/releases/download/v$VERSION/checksums.txt"

echo -e "${YELLOW}⬇${NC} Downloading $DOWNLOAD_FILE..."

TMP_DIR=$(mktemp -d)
cd "$TMP_DIR"

# Download the binary/package
if ! curl -fsSL -o "$DOWNLOAD_FILE" "$DOWNLOAD_URL"; then
echo -e "${RED}❌ Download failed${NC}"
rm -rf "$TMP_DIR"
exit 1
fi

# Download checksums
echo -e "${YELLOW}🔐${NC} Verifying checksum..."
if ! curl -fsSL -o "checksums.txt" "$CHECKSUM_URL"; then
echo -e "${RED}❌ Failed to download checksums${NC}"
rm -rf "$TMP_DIR"
exit 1
fi

# Verify checksum
EXPECTED_CHECKSUM=$(grep "$DOWNLOAD_FILE" checksums.txt | awk '{print $1}')
if [ -z "$EXPECTED_CHECKSUM" ]; then
echo -e "${RED}❌ Checksum not found for $DOWNLOAD_FILE${NC}"
rm -rf "$TMP_DIR"
exit 1
fi

ACTUAL_CHECKSUM=$(sha256sum "$DOWNLOAD_FILE" | awk '{print $1}')
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then
echo -e "${RED}❌ Checksum verification failed!${NC}"
echo -e "${RED} Expected: $EXPECTED_CHECKSUM${NC}"
echo -e "${RED} Got: $ACTUAL_CHECKSUM${NC}"
echo -e "${RED} This may indicate a compromised download.${NC}"
rm -rf "$TMP_DIR"
exit 1
fi

echo -e "${GREEN}✓${NC} Checksum verified"
echo -e "${YELLOW}📦${NC} Installing..."

if [ "$INSTALL_CMD" = "tar" ]; then
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9.0.1
9.1.0
14 changes: 11 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"os/user"
"path/filepath"

"BanglaCode/src/Update"
"BanglaCode/src/evaluator"
"BanglaCode/src/evaluator/builtins"
"BanglaCode/src/lexer"
Expand All @@ -27,7 +28,12 @@ func main() {
return
}

// Check for flags
// Check for commands and flags
if len(os.Args) == 2 && update.CheckUpdateCommand(os.Args[1:], "update") {

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition checks both that len(os.Args) == 2 AND that CheckUpdateCommand returns true. The CheckUpdateCommand function already validates the argument value, making the length check partially redundant with how it's being called. More importantly, this means "banglacode -h update" or "banglacode update extra-arg" would not trigger the update command, which may be unexpected behavior. Consider either: 1) Simplifying to just check for the "update" command regardless of other arguments, or 2) Explicitly validating that "update" is the only argument and showing an error for extra arguments.

Suggested change
if len(os.Args) == 2 && update.CheckUpdateCommand(os.Args[1:], "update") {
if update.CheckUpdateCommand(os.Args[1:], "update") {
if len(os.Args) != 2 {
fmt.Fprintln(os.Stderr, "Error: 'update' command does not accept additional arguments.")
return
}

Copilot uses AI. Check for mistakes.
update.Updater()
return
}

if os.Args[1] == "--help" || os.Args[1] == "-h" {
printHelp()
return
Expand Down Expand Up @@ -55,6 +61,7 @@ func printHelp() {
fmt.Println("\033[1;33m▸ Usage:\033[0m")
fmt.Println(" \033[1;32mbanglacode\033[0m Start interactive REPL")
fmt.Println(" \033[1;32mbanglacode <file>\033[0m Execute a BanglaCode file")
fmt.Println(" \033[1;32mbanglacode update\033[0m Update to the latest version")
fmt.Println(" \033[1;32mbanglacode --help, -h\033[0m Show this help message")
fmt.Println(" \033[1;32mbanglacode --version, -v\033[0m Show version information")
fmt.Println("")
Expand All @@ -66,6 +73,7 @@ func printHelp() {
fmt.Println(" \033[0;34m$\033[0m banglacode hello.bang \033[2m# Run hello.bang file\033[0m")
fmt.Println(" \033[0;34m$\033[0m banglacode app.bangla \033[2m# Run app.bangla file\033[0m")
fmt.Println(" \033[0;34m$\033[0m banglacode server.bong \033[2m# Run server.bong file\033[0m")
fmt.Println(" \033[0;34m$\033[0m banglacode update \033[2m# Update to latest version\033[0m")
fmt.Println("")
fmt.Println("\033[1;36m╚══════════════════════════════════════════════════════════════════╝\033[0m")
fmt.Println(" 📄 For more information, see \033[1;35mSYNTAX.md\033[0m")
Expand All @@ -74,10 +82,10 @@ func printHelp() {

func printVersion() {
fmt.Println("\033[1;36m╔════════════════════════════════════════════════════════╗")
fmt.Println("║ BanglaCode v9.0.1 ║")
fmt.Println("║ BanglaCode v9.1.0 ║")
fmt.Println("║ A Programming Language in Bengali (Banglish) ║")
fmt.Println("╠════════════════════════════════════════════════════════╣\033[0m")
fmt.Println("\033[1;36m║\033[0m 📦 \033[1mVersion:\033[0m \033[1;32m9.0.1\033[0m \033[1;36m║\033[0m")
fmt.Println("\033[1;36m║\033[0m 📦 \033[1mVersion:\033[0m \033[1;32m9.1.0\033[0m \033[1;36m║\033[0m")
Comment on lines +85 to +88

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version strings are hardcoded in the printVersion function. This creates a maintenance burden and risk of version mismatch. Consider using the Version constant from the repl package (repl.Version) instead of hardcoding the version string twice. This would ensure consistency and make version updates less error-prone.

Copilot uses AI. Check for mistakes.
fmt.Println("\033[1;36m║\033[0m 👨‍💻 \033[1mAuthor:\033[0m \033[1;35mAnkan Saha\033[0m \033[1;36m║\033[0m")
fmt.Println("\033[1;36m║\033[0m 🌍 \033[1mFrom:\033[0m \033[1;37mWest Bengal, India\033[0m \033[1;36m║\033[0m")
fmt.Println("\033[1;36m║\033[0m 🔗 \033[1mGitHub:\033[0m \033[1;34mhttps://github.com/nexoral/BanglaCode\033[0m \033[1;36m║\033[0m")
Expand Down
77 changes: 77 additions & 0 deletions src/Update/Updater.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package update

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The directory is named "Update" (capitalized) which is inconsistent with Go naming conventions. All other packages in the codebase use lowercase directory names (e.g., src/repl/, src/parser/, src/evaluator/builtins/crypto/). The directory should be renamed to "update" to match Go conventions and maintain consistency with the rest of the codebase.

Copilot uses AI. Check for mistakes.

import (
"fmt"
"os"
"os/exec"
"runtime"
"strings"
)

// Update commands for each operating system
var updateCommands = map[string]updateCommand{
"linux": {
shell: "bash",
shellArg: "-c",
script: "curl -fsSL https://raw.githubusercontent.com/nexoral/BanglaCode/main/Scripts/install.sh | bash",
},
"darwin": {
shell: "bash",
shellArg: "-c",
script: "curl -fsSL https://raw.githubusercontent.com/nexoral/BanglaCode/main/Scripts/install.sh | bash",
},
"windows": {
shell: "powershell",
shellArg: "-Command",
script: "irm https://raw.githubusercontent.com/nexoral/BanglaCode/main/Scripts/install.ps1 | iex",
},
Comment on lines +16 to +27

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The update mechanism downloads and executes remote scripts without any verification that the script contents match what's expected. While the install scripts themselves now verify checksums of binaries (as seen in Scripts/install.sh), the updater executes the install scripts themselves without any integrity check. An attacker who compromises the GitHub repository or performs a man-in-the-middle attack could inject malicious code that would be executed with the user's privileges. Consider one of these alternatives: 1) Download the script, verify its checksum, then execute it locally, 2) Use a native Go implementation that directly downloads and verifies binaries, or 3) At minimum, document this security risk prominently in user-facing documentation.

Copilot uses AI. Check for mistakes.
}

type updateCommand struct {
shell string
shellArg string
script string
}

// Update checks if the update command was passed and executes the appropriate update script
func Updater() {

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function comment says "Update checks if the update command was passed" but the function doesn't check for command arguments - it directly executes the update. The comment should describe what the function actually does: executing the update process for the detected OS. Consider renaming this function to "Execute" or "Run" to better reflect its behavior, or update the comment to match the actual implementation.

Copilot uses AI. Check for mistakes.
fmt.Println("\033[1;36m╔════════════════════════════════════════════════════════╗")
fmt.Println("║ Updating BanglaCode... ║")
fmt.Println("╚════════════════════════════════════════════════════════╝\033[0m")
fmt.Println()

// Detect operating system
currentOS := runtime.GOOS
cmd, exists := updateCommands[currentOS]

if !exists {
fmt.Fprintf(os.Stderr, "\033[31mError: Unsupported operating system '%s'\033[0m\n", currentOS)
fmt.Fprintf(os.Stderr, "Supported systems: Linux, macOS (darwin), Windows\n")
os.Exit(1)
}

fmt.Printf("Detected OS: \033[1;32m%s\033[0m\n", currentOS)
fmt.Printf("Running update command...\n\n")

// Execute the appropriate update command
command := exec.Command(cmd.shell, cmd.shellArg, cmd.script)
command.Stdout = os.Stdout
command.Stderr = os.Stderr

if err := command.Run(); err != nil {
fmt.Fprintf(os.Stderr, "\n\033[31mError: Update failed: %v\033[0m\n", err)
os.Exit(1)
}

fmt.Println("\n\033[1;32m✓ Update completed successfully!\033[0m")
}
Comment on lines +37 to +67

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation calls os.Exit(1) directly on error, which prevents proper cleanup and makes the function difficult to test. This pattern is inconsistent with Go best practices for library code. Consider returning an error value instead and letting the caller (main.go) decide when to exit. This would make the update package more testable and reusable.

Copilot uses AI. Check for mistakes.

// checkUpdateCommand checks if the "update" argument is present in the command-line args

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says "checkUpdateCommand" (lowercase) but the function is actually named "CheckUpdateCommand" (uppercase/exported). The comment should match the actual function name for consistency and to avoid confusion.

Suggested change
// checkUpdateCommand checks if the "update" argument is present in the command-line args
// CheckUpdateCommand checks if the "update" argument is present in the command-line args

Copilot uses AI. Check for mistakes.
func CheckUpdateCommand(args []string, target string) bool {

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CheckUpdateCommand function is exported (starts with capital letter) but only used within main.go. Based on Go conventions and examining similar system packages in this codebase (like src/evaluator/builtins/system/), internal helper functions should be unexported unless they need to be part of the public API. Consider making this function unexported by renaming it to "checkUpdateCommand".

Copilot uses AI. Check for mistakes.
for _, arg := range args {
if strings.ToLower(arg) == target {
return true
}
}
return false
}
Comment on lines +70 to +77

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function accepts a generic "target" parameter but it's only ever called with the hardcoded value "update". This adds unnecessary complexity. Consider simplifying the function signature to not take a target parameter, or document why this flexibility is needed if there are plans to support other commands in the future.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +77

Copilot AI Feb 23, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new Update package lacks test coverage. Given that this codebase has comprehensive test coverage for other packages (as seen in the test directory), the update functionality should also have tests. Consider adding tests that: 1) Verify CheckUpdateCommand correctly identifies the update argument, 2) Mock the exec.Command to test different OS scenarios without actually executing shell commands, 3) Test error handling for unsupported operating systems. This is particularly important for security-sensitive code that executes external commands.

Copilot uses AI. Check for mistakes.
2 changes: 1 addition & 1 deletion src/repl/repl.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"strings"
)

const Version = "9.0.1"
const Version = "9.1.0"

const PROMPT = "\033[1;33m>> \033[0m"

Expand Down