refactor: use python instead of javascript

This commit is contained in:
Bjarke Sporring
2026-01-05 12:21:48 +01:00
parent e1b8d8418a
commit f11f5a4646
14 changed files with 550 additions and 735 deletions

View File

@@ -40,88 +40,78 @@ git commit -m "Initial commit" | Out-Null
# Commit 1: WIP user profile # Commit 1: WIP user profile
$userProfile = @" $userProfile = @"
class UserProfile { class UserProfile:
constructor(name, email) { def __init__(self, name, email):
this.name = name; self.name = name
this.email = email; self.email = email
}
}
"@ "@
Set-Content -Path "user-profile.js" -Value $userProfile Set-Content -Path "user_profile.py" -Value $userProfile
git add user-profile.js git add user_profile.py
git commit -m "WIP: user profile" | Out-Null git commit -m "WIP: user profile" | Out-Null
# Commit 2: Add validation (typo in message) # Commit 2: Add validation (typo in message)
$userProfileWithValidation = @" $userProfileWithValidation = @"
class UserProfile { class UserProfile:
constructor(name, email) { def __init__(self, name, email):
this.name = name; self.name = name
this.email = email; self.email = email
}
validate() { def validate(self):
if (!this.name || !this.email) { if not self.name or not self.email:
throw new Error('Name and email are required'); raise ValueError('Name and email are required')
} return True
return true;
}
}
"@ "@
Set-Content -Path "user-profile.js" -Value $userProfileWithValidation Set-Content -Path "user_profile.py" -Value $userProfileWithValidation
git add user-profile.js git add user_profile.py
git commit -m "add validaton" | Out-Null # Intentional typo git commit -m "add validaton" | Out-Null # Intentional typo
# Commit 3: Fix validation # Commit 3: Fix validation
$userProfileFixed = @" $userProfileFixed = @"
class UserProfile { class UserProfile:
constructor(name, email) { def __init__(self, name, email):
this.name = name; self.name = name
this.email = email; self.email = email
}
validate() { def validate(self):
if (!this.name || !this.email) { if not self.name or not self.email:
throw new Error('Name and email are required'); raise ValueError('Name and email are required')
} if '@' not in self.email:
if (!this.email.includes('@')) { raise ValueError('Invalid email format')
throw new Error('Invalid email format'); return True
}
return true;
}
}
"@ "@
Set-Content -Path "user-profile.js" -Value $userProfileFixed Set-Content -Path "user_profile.py" -Value $userProfileFixed
git add user-profile.js git add user_profile.py
git commit -m "fix validation bug" | Out-Null git commit -m "fix validation bug" | Out-Null
# Commit 4: Add tests (another WIP commit) # Commit 4: Add tests (another WIP commit)
$tests = @" $tests = @"
const assert = require('assert'); import unittest
const UserProfile = require('./user-profile'); from user_profile import UserProfile
describe('UserProfile', () => { class TestUserProfile(unittest.TestCase):
it('should validate correct user data', () => { def test_validate_correct_user_data(self):
const user = new UserProfile('John', 'john@example.com'); user = UserProfile('John', 'john@example.com')
assert.strictEqual(user.validate(), true); self.assertTrue(user.validate())
});
it('should reject missing name', () => { def test_reject_missing_name(self):
const user = new UserProfile('', 'john@example.com'); user = UserProfile('', 'john@example.com')
assert.throws(() => user.validate()); with self.assertRaises(ValueError):
}); user.validate()
it('should reject invalid email', () => { def test_reject_invalid_email(self):
const user = new UserProfile('John', 'invalid-email'); user = UserProfile('John', 'invalid-email')
assert.throws(() => user.validate()); with self.assertRaises(ValueError):
}); user.validate()
});
if __name__ == '__main__':
unittest.main()
"@ "@
Set-Content -Path "user-profile.test.js" -Value $tests Set-Content -Path "test_user_profile.py" -Value $tests
git add user-profile.test.js git add test_user_profile.py
git commit -m "WIP tests" | Out-Null git commit -m "WIP tests" | Out-Null
# Return to module directory # Return to module directory

View File

@@ -86,70 +86,70 @@ if ($featureCommit.Length -lt 10) {
} }
# Check that required files exist # Check that required files exist
if (-not (Test-Path "user-profile.js")) { if (-not (Test-Path "user_profile.py")) {
Write-Host "[FAIL] user-profile.js not found." -ForegroundColor Red Write-Host "[FAIL] user_profile.py not found." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
if (-not (Test-Path "user-profile.test.js")) { if (-not (Test-Path "test_user_profile.py")) {
Write-Host "[FAIL] user-profile.test.js not found." -ForegroundColor Red Write-Host "[FAIL] test_user_profile.py not found." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Check that user-profile.js contains all expected features # Check that user_profile.py contains all expected features
$userProfileContent = Get-Content "user-profile.js" -Raw $userProfileContent = Get-Content "user_profile.py" -Raw
# Should have the class # Should have the class
if ($userProfileContent -notmatch "class UserProfile") { if ($userProfileContent -notmatch "class UserProfile") {
Write-Host "[FAIL] user-profile.js should contain UserProfile class." -ForegroundColor Red Write-Host "[FAIL] user_profile.py should contain UserProfile class." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Should have validation method # Should have validation method
if ($userProfileContent -notmatch "validate\(\)") { if ($userProfileContent -notmatch "def validate\(") {
Write-Host "[FAIL] user-profile.js should contain validate() method." -ForegroundColor Red Write-Host "[FAIL] user_profile.py should contain validate() method." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Should have email format validation (the final fix from commit 3) # Should have email format validation (the final fix from commit 3)
if ($userProfileContent -notmatch "includes\('@'\)") { if ($userProfileContent -notmatch "'@'.*in.*email|email.*in.*'@'") {
Write-Host "[FAIL] user-profile.js should contain email format validation." -ForegroundColor Red Write-Host "[FAIL] user_profile.py should contain email format validation." -ForegroundColor Red
Write-Host "Hint: Make sure all changes from all 4 commits are included." -ForegroundColor Yellow Write-Host "Hint: Make sure all changes from all 4 commits are included." -ForegroundColor Yellow
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Check that test file has content # Check that test file has content
$testContent = Get-Content "user-profile.test.js" -Raw $testContent = Get-Content "test_user_profile.py" -Raw
if ($testContent -notmatch "describe.*UserProfile") { if ($testContent -notmatch "class.*TestUserProfile") {
Write-Host "[FAIL] user-profile.test.js should contain UserProfile tests." -ForegroundColor Red Write-Host "[FAIL] test_user_profile.py should contain TestUserProfile tests." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Check that we have at least 3 test cases # Check that we have at least 3 test cases
$testMatches = ([regex]::Matches($testContent, "it\(")).Count $testMatches = ([regex]::Matches($testContent, "def test_")).Count
if ($testMatches -lt 3) { if ($testMatches -lt 3) {
Write-Host "[FAIL] user-profile.test.js should contain at least 3 test cases." -ForegroundColor Red Write-Host "[FAIL] test_user_profile.py should contain at least 3 test cases." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Verify that the latest commit contains changes to both files # Verify that the latest commit contains changes to both files
$filesInLastCommit = git diff-tree --no-commit-id --name-only -r HEAD 2>$null $filesInLastCommit = git diff-tree --no-commit-id --name-only -r HEAD 2>$null
if ($filesInLastCommit -notcontains "user-profile.js") { if ($filesInLastCommit -notcontains "user_profile.py") {
Write-Host "[FAIL] The feature commit should include user-profile.js" -ForegroundColor Red Write-Host "[FAIL] The feature commit should include user_profile.py" -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
if ($filesInLastCommit -notcontains "user-profile.test.js") { if ($filesInLastCommit -notcontains "test_user_profile.py") {
Write-Host "[FAIL] The feature commit should include user-profile.test.js" -ForegroundColor Red Write-Host "[FAIL] The feature commit should include test_user_profile.py" -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }

View File

@@ -28,21 +28,16 @@ git config user.email "user@workshop.local" | Out-Null
# Create initial commits on main branch # Create initial commits on main branch
$app = @" $app = @"
class App { class App:
constructor() { def __init__(self):
this.version = '1.0.0'; self.version = '1.0.0'
}
start() { def start(self):
console.log('App started'); print('App started')
}
}
module.exports = App;
"@ "@
Set-Content -Path "app.js" -Value $app Set-Content -Path "app.py" -Value $app
git add app.js git add app.py
git commit -m "Initial app implementation" | Out-Null git commit -m "Initial app implementation" | Out-Null
$readme = @" $readme = @"
@@ -60,132 +55,104 @@ git checkout -b development | Out-Null
# Commit 1: Experimental feature (should NOT be cherry-picked) # Commit 1: Experimental feature (should NOT be cherry-picked)
$appWithExperimental = @" $appWithExperimental = @"
class App { class App:
constructor() { def __init__(self):
this.version = '1.0.0'; self.version = '1.0.0'
this.experimentalMode = false; self.experimental_mode = False
}
start() { def start(self):
console.log('App started'); print('App started')
if (this.experimentalMode) { if self.experimental_mode:
this.enableExperimentalFeatures(); self.enable_experimental_features()
}
}
enableExperimentalFeatures() { def enable_experimental_features(self):
console.log('Experimental features enabled'); print('Experimental features enabled')
}
}
module.exports = App;
"@ "@
Set-Content -Path "app.js" -Value $appWithExperimental Set-Content -Path "app.py" -Value $appWithExperimental
git add app.js git add app.py
git commit -m "Add experimental AI features" | Out-Null git commit -m "Add experimental AI features" | Out-Null
# Commit 2: Security bug fix (SHOULD be cherry-picked) # Commit 2: Security bug fix (SHOULD be cherry-picked)
$security = @" $security = @"
class Security { import re
static sanitizeInput(input) {
// Remove potential XSS attacks
return input.replace(/[<>]/g, '');
}
static validateToken(token) { class Security:
if (!token || token.length < 32) { @staticmethod
throw new Error('Invalid security token'); def sanitize_input(input_str):
} # Remove potential XSS attacks
return true; return re.sub(r'[<>]', '', input_str)
}
}
module.exports = Security; @staticmethod
def validate_token(token):
if not token or len(token) < 32:
raise ValueError('Invalid security token')
return True
"@ "@
Set-Content -Path "security.js" -Value $security Set-Content -Path "security.py" -Value $security
git add security.js git add security.py
git commit -m "Fix security vulnerability in input validation" | Out-Null git commit -m "Fix security vulnerability in input validation" | Out-Null
# Commit 3: Another experimental feature (should NOT be cherry-picked) # Commit 3: Another experimental feature (should NOT be cherry-picked)
$appWithMoreExperimental = @" $appWithMoreExperimental = @"
class App { class App:
constructor() { def __init__(self):
this.version = '1.0.0'; self.version = '1.0.0'
this.experimentalMode = false; self.experimental_mode = False
this.betaFeatures = []; self.beta_features = []
}
start() { def start(self):
console.log('App started'); print('App started')
if (this.experimentalMode) { if self.experimental_mode:
this.enableExperimentalFeatures(); self.enable_experimental_features()
}
}
enableExperimentalFeatures() { def enable_experimental_features(self):
console.log('Experimental features enabled'); print('Experimental features enabled')
}
addBetaFeature(feature) { def add_beta_feature(self, feature):
this.betaFeatures.push(feature); self.beta_features.append(feature)
}
}
module.exports = App;
"@ "@
Set-Content -Path "app.js" -Value $appWithMoreExperimental Set-Content -Path "app.py" -Value $appWithMoreExperimental
git add app.js git add app.py
git commit -m "Add beta features framework" | Out-Null git commit -m "Add beta features framework" | Out-Null
# Commit 4: Performance bug fix (SHOULD be cherry-picked) # Commit 4: Performance bug fix (SHOULD be cherry-picked)
$appWithPerformance = @" $appWithPerformance = @"
class App { class App:
constructor() { def __init__(self):
this.version = '1.0.0'; self.version = '1.0.0'
this.experimentalMode = false; self.experimental_mode = False
this.betaFeatures = []; self.beta_features = []
this.cache = new Map(); self.cache = {}
}
start() { def start(self):
console.log('App started'); print('App started')
if (this.experimentalMode) { if self.experimental_mode:
this.enableExperimentalFeatures(); self.enable_experimental_features()
}
}
enableExperimentalFeatures() { def enable_experimental_features(self):
console.log('Experimental features enabled'); print('Experimental features enabled')
}
addBetaFeature(feature) { def add_beta_feature(self, feature):
this.betaFeatures.push(feature); self.beta_features.append(feature)
}
getData(key) { def get_data(self, key):
// Use cache to improve performance # Use cache to improve performance
if (this.cache.has(key)) { if key in self.cache:
return this.cache.get(key); return self.cache[key]
} data = self.fetch_data(key)
const data = this.fetchData(key); self.cache[key] = data
this.cache.set(key, data); return data
return data;
}
fetchData(key) { def fetch_data(self, key):
// Simulate data fetching # Simulate data fetching
return { key: key, value: 'data' }; return {'key': key, 'value': 'data'}
}
}
module.exports = App;
"@ "@
Set-Content -Path "app.js" -Value $appWithPerformance Set-Content -Path "app.py" -Value $appWithPerformance
git add app.js git add app.py
git commit -m "Fix performance issue with data caching" | Out-Null git commit -m "Fix performance issue with data caching" | Out-Null
# Return to module directory # Return to module directory

View File

@@ -80,71 +80,71 @@ if ($mergeCommits) {
exit 1 exit 1
} }
# Check that security.js exists (from the security fix commit) # Check that security.py exists (from the security fix commit)
if (-not (Test-Path "security.js")) { if (-not (Test-Path "security.py")) {
Write-Host "[FAIL] security.js not found on main branch." -ForegroundColor Red Write-Host "[FAIL] security.py not found on main branch." -ForegroundColor Red
Write-Host "Hint: You need to cherry-pick the 'Fix security vulnerability' commit" -ForegroundColor Yellow Write-Host "Hint: You need to cherry-pick the 'Fix security vulnerability' commit" -ForegroundColor Yellow
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Check that security.js has the security fix # Check that security.py has the security fix
$securityContent = Get-Content "security.js" -Raw $securityContent = Get-Content "security.py" -Raw
if ($securityContent -notmatch "sanitizeInput") { if ($securityContent -notmatch "sanitize_input") {
Write-Host "[FAIL] security.js is missing the sanitizeInput function." -ForegroundColor Red Write-Host "[FAIL] security.py is missing the sanitize_input function." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
if ($securityContent -notmatch "validateToken") { if ($securityContent -notmatch "validate_token") {
Write-Host "[FAIL] security.js is missing the validateToken function." -ForegroundColor Red Write-Host "[FAIL] security.py is missing the validate_token function." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Check that app.js exists # Check that app.py exists
if (-not (Test-Path "app.js")) { if (-not (Test-Path "app.py")) {
Write-Host "[FAIL] app.js not found." -ForegroundColor Red Write-Host "[FAIL] app.py not found." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Check that app.js has the performance fix (cache) but NOT experimental features # Check that app.py has the performance fix (cache) but NOT experimental features
$appContent = Get-Content "app.js" -Raw $appContent = Get-Content "app.py" -Raw
# Should have cache (from performance fix) # Should have cache (from performance fix)
if ($appContent -notmatch "cache") { if ($appContent -notmatch "cache") {
Write-Host "[FAIL] app.js is missing the performance fix (cache)." -ForegroundColor Red Write-Host "[FAIL] app.py is missing the performance fix (cache)." -ForegroundColor Red
Write-Host "Hint: You need to cherry-pick the 'Fix performance issue' commit" -ForegroundColor Yellow Write-Host "Hint: You need to cherry-pick the 'Fix performance issue' commit" -ForegroundColor Yellow
Set-Location .. Set-Location ..
exit 1 exit 1
} }
if ($appContent -notmatch "getData") { if ($appContent -notmatch "get_data") {
Write-Host "[FAIL] app.js is missing the getData method from performance fix." -ForegroundColor Red Write-Host "[FAIL] app.py is missing the get_data method from performance fix." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Should NOT have experimental features # Should NOT have experimental features
if ($appContent -match "experimentalMode") { if ($appContent -match "experimental_mode") {
Write-Host "[FAIL] app.js contains experimental features (experimentalMode)." -ForegroundColor Red Write-Host "[FAIL] app.py contains experimental features (experimental_mode)." -ForegroundColor Red
Write-Host "Hint: You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow Write-Host "Hint: You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow
Write-Host " The experimental feature commits should stay on development branch only" -ForegroundColor Yellow Write-Host " The experimental feature commits should stay on development branch only" -ForegroundColor Yellow
Set-Location .. Set-Location ..
exit 1 exit 1
} }
if ($appContent -match "betaFeatures") { if ($appContent -match "beta_features") {
Write-Host "[FAIL] app.js contains experimental features (betaFeatures)." -ForegroundColor Red Write-Host "[FAIL] app.py contains experimental features (beta_features)." -ForegroundColor Red
Write-Host "Hint: You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow Write-Host "Hint: You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow
Set-Location .. Set-Location ..
exit 1 exit 1
} }
if ($appContent -match "enableExperimentalFeatures") { if ($appContent -match "enable_experimental_features") {
Write-Host "[FAIL] app.js contains experimental features (enableExperimentalFeatures)." -ForegroundColor Red Write-Host "[FAIL] app.py contains experimental features (enable_experimental_features)." -ForegroundColor Red
Write-Host "Hint: You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow Write-Host "Hint: You should cherry-pick ONLY the bug fixes, not experimental features" -ForegroundColor Yellow
Set-Location .. Set-Location ..
exit 1 exit 1

View File

@@ -28,21 +28,16 @@ git config user.email "user@workshop.local" | Out-Null
# Create initial commits on main # Create initial commits on main
$app = @" $app = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a + b; return a + b
}
subtract(a, b) { def subtract(self, a, b):
return a - b; return a - b
}
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $app Set-Content -Path "calculator.py" -Value $app
git add calculator.js git add calculator.py
git commit -m "Initial calculator implementation" | Out-Null git commit -m "Initial calculator implementation" | Out-Null
$readme = @" $readme = @"
@@ -59,54 +54,41 @@ git commit -m "Add README" | Out-Null
git checkout -b local-feature | Out-Null git checkout -b local-feature | Out-Null
$appWithMultiply = @" $appWithMultiply = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a + b; return a + b
}
subtract(a, b) { def subtract(self, a, b):
return a - b; return a - b
}
multiply(a, b) { def multiply(self, a, b):
return a * b; return a * b
}
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $appWithMultiply Set-Content -Path "calculator.py" -Value $appWithMultiply
git add calculator.js git add calculator.py
git commit -m "Add multiply function" | Out-Null git commit -m "Add multiply function" | Out-Null
# Add a bad commit that should be removed with reset # Add a bad commit that should be removed with reset
$appWithBadCode = @" $appWithBadCode = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a + b; return a + b
}
subtract(a, b) { def subtract(self, a, b):
return a - b; return a - b
}
multiply(a, b) { def multiply(self, a, b):
return a * b; return a * b
}
// BUG: This is broken and should never have been committed! # BUG: This is broken and should never have been committed!
divide(a, b) { def divide(self, a, b):
// Forgot to check for division by zero # Forgot to check for division by zero
return a / b; // This will return Infinity or NaN for zero! return a / b # This will raise ZeroDivisionError for zero!
}
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $appWithBadCode Set-Content -Path "calculator.py" -Value $appWithBadCode
git add calculator.js git add calculator.py
git commit -m "Add broken divide function - DO NOT KEEP" | Out-Null git commit -m "Add broken divide function - DO NOT KEEP" | Out-Null
# Switch back to main for shared-feature branch # Switch back to main for shared-feature branch
@@ -116,87 +98,70 @@ git checkout main | Out-Null
git checkout -b shared-feature | Out-Null git checkout -b shared-feature | Out-Null
$appWithPower = @" $appWithPower = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a + b; return a + b
}
subtract(a, b) { def subtract(self, a, b):
return a - b; return a - b
}
power(a, b) { def power(self, a, b):
return Math.pow(a, b); return a ** b
}
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $appWithPower Set-Content -Path "calculator.py" -Value $appWithPower
git add calculator.js git add calculator.py
git commit -m "Add power function" | Out-Null git commit -m "Add power function" | Out-Null
# Add a bad commit that should be reverted (not reset) # Add a bad commit that should be reverted (not reset)
$appWithBrokenFeature = @" $appWithBrokenFeature = @"
class Calculator { import math
add(a, b) {
return a + b;
}
subtract(a, b) { class Calculator:
return a - b; def add(self, a, b):
} return a + b
power(a, b) { def subtract(self, a, b):
return Math.pow(a, b); return a - b
}
// BUG: This breaks the calculator! def power(self, a, b):
squareRoot(a) { return a ** b
// This implementation is wrong for negative numbers
return Math.sqrt(a); // Returns NaN for negative numbers without warning!
}
}
module.exports = Calculator; # BUG: This breaks the calculator!
def square_root(self, a):
# This implementation is wrong for negative numbers
return math.sqrt(a) # Raises ValueError for negative numbers without warning!
"@ "@
Set-Content -Path "calculator.js" -Value $appWithBrokenFeature Set-Content -Path "calculator.py" -Value $appWithBrokenFeature
git add calculator.js git add calculator.py
git commit -m "Add broken feature" | Out-Null git commit -m "Add broken feature" | Out-Null
# Add another good commit after the bad one (to show that revert preserves subsequent commits) # Add another good commit after the bad one (to show that revert preserves subsequent commits)
$appWithMoreFeatures = @" $appWithMoreFeatures = @"
class Calculator { import math
add(a, b) {
return a + b;
}
subtract(a, b) { class Calculator:
return a - b; def add(self, a, b):
} return a + b
power(a, b) { def subtract(self, a, b):
return Math.pow(a, b); return a - b
}
// BUG: This breaks the calculator! def power(self, a, b):
squareRoot(a) { return a ** b
// This implementation is wrong for negative numbers
return Math.sqrt(a); // Returns NaN for negative numbers without warning!
}
modulo(a, b) { # BUG: This breaks the calculator!
return a % b; def square_root(self, a):
} # This implementation is wrong for negative numbers
} return math.sqrt(a) # Raises ValueError for negative numbers without warning!
module.exports = Calculator; def modulo(self, a, b):
return a % b
"@ "@
Set-Content -Path "calculator.js" -Value $appWithMoreFeatures Set-Content -Path "calculator.py" -Value $appWithMoreFeatures
git add calculator.js git add calculator.py
git commit -m "Add modulo function" | Out-Null git commit -m "Add modulo function" | Out-Null
# Switch to local-feature for the challenge start # Switch to local-feature for the challenge start

View File

@@ -49,26 +49,26 @@ if ($localCommitCount -ne 3) {
exit 1 exit 1
} }
# Check that calculator.js exists # Check that calculator.py exists
if (-not (Test-Path "calculator.js")) { if (-not (Test-Path "calculator.py")) {
Write-Host "[FAIL] calculator.js not found." -ForegroundColor Red Write-Host "[FAIL] calculator.py not found." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Check calculator.js on local-feature # Check calculator.py on local-feature
$localCalcContent = Get-Content "calculator.js" -Raw $localCalcContent = Get-Content "calculator.py" -Raw
# Should have multiply function # Should have multiply function
if ($localCalcContent -notmatch "multiply") { if ($localCalcContent -notmatch "multiply") {
Write-Host "[FAIL] calculator.js should have the multiply function." -ForegroundColor Red Write-Host "[FAIL] calculator.py should have the multiply function." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Should NOT have divide function (it was in the bad commit that should be reset) # Should NOT have divide function (it was in the bad commit that should be reset)
if ($localCalcContent -match "divide") { if ($localCalcContent -match "divide") {
Write-Host "[FAIL] calculator.js should NOT have the divide function." -ForegroundColor Red Write-Host "[FAIL] calculator.py should NOT have the divide function." -ForegroundColor Red
Write-Host "Hint: Use 'git reset --hard HEAD~1' to remove the bad commit" -ForegroundColor Yellow Write-Host "Hint: Use 'git reset --hard HEAD~1' to remove the bad commit" -ForegroundColor Yellow
Set-Location .. Set-Location ..
exit 1 exit 1
@@ -115,27 +115,27 @@ if ($sharedCommits -notmatch "Revert") {
exit 1 exit 1
} }
# Check calculator.js on shared-feature # Check calculator.py on shared-feature
$sharedCalcContent = Get-Content "calculator.js" -Raw $sharedCalcContent = Get-Content "calculator.py" -Raw
# Should have power function # Should have power function
if ($sharedCalcContent -notmatch "power") { if ($sharedCalcContent -notmatch "power") {
Write-Host "[FAIL] calculator.js should have the power function." -ForegroundColor Red Write-Host "[FAIL] calculator.py should have the power function." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Should have modulo function (commits after the reverted one should be preserved) # Should have modulo function (commits after the reverted one should be preserved)
if ($sharedCalcContent -notmatch "modulo") { if ($sharedCalcContent -notmatch "modulo") {
Write-Host "[FAIL] calculator.js should have the modulo function." -ForegroundColor Red Write-Host "[FAIL] calculator.py should have the modulo function." -ForegroundColor Red
Write-Host "Hint: Reverting should preserve commits made after the bad one" -ForegroundColor Yellow Write-Host "Hint: Reverting should preserve commits made after the bad one" -ForegroundColor Yellow
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Should NOT have squareRoot function (it was in the bad commit that should be reverted) # Should NOT have square_root function (it was in the bad commit that should be reverted)
if ($sharedCalcContent -match "squareRoot") { if ($sharedCalcContent -match "square_root") {
Write-Host "[FAIL] calculator.js should NOT have the squareRoot function." -ForegroundColor Red Write-Host "[FAIL] calculator.py should NOT have the square_root function." -ForegroundColor Red
Write-Host "Hint: The 'Add broken feature' commit should be reverted" -ForegroundColor Yellow Write-Host "Hint: The 'Add broken feature' commit should be reverted" -ForegroundColor Yellow
Write-Host " Use: git revert <commit-hash-of-broken-feature>" -ForegroundColor Yellow Write-Host " Use: git revert <commit-hash-of-broken-feature>" -ForegroundColor Yellow
Set-Location .. Set-Location ..
@@ -146,7 +146,7 @@ if ($sharedCalcContent -match "squareRoot") {
$revertCommitMessage = git log --grep="Revert" --pretty=format:"%s" -n 1 2>$null $revertCommitMessage = git log --grep="Revert" --pretty=format:"%s" -n 1 2>$null
if ($revertCommitMessage -notmatch "broken feature") { if ($revertCommitMessage -notmatch "broken feature") {
Write-Host "[FAIL] The revert commit should mention 'broken feature'." -ForegroundColor Red Write-Host "[FAIL] The revert commit should mention 'broken feature'." -ForegroundColor Red
Write-Host "Hint: Make sure you reverted the correct commit (the one that added squareRoot)" -ForegroundColor Yellow Write-Host "Hint: Make sure you reverted the correct commit (the one that added square_root)" -ForegroundColor Yellow
Set-Location .. Set-Location ..
exit 1 exit 1
} }

View File

@@ -27,28 +27,22 @@ git config user.email "user@workshop.local" | Out-Null
# Create initial application on main # Create initial application on main
$app = @" $app = @"
class Application { class Application:
constructor() { def __init__(self):
this.name = 'MyApp'; self.name = 'MyApp'
this.version = '1.0.0'; self.version = '1.0.0'
}
start() { def start(self):
console.log('Application started'); print('Application started')
this.authenticate(); self.authenticate()
}
authenticate() { def authenticate(self):
console.log('Authentication check'); print('Authentication check')
return true; return True
}
}
module.exports = Application;
"@ "@
Set-Content -Path "app.js" -Value $app Set-Content -Path "app.py" -Value $app
git add app.js git add app.py
git commit -m "Initial application" | Out-Null git commit -m "Initial application" | Out-Null
$readme = @" $readme = @"
@@ -66,54 +60,44 @@ git checkout -b feature-login | Out-Null
# Start working on login feature # Start working on login feature
$loginInitial = @" $loginInitial = @"
class LoginService { from datetime import datetime
constructor() {
this.users = new Map();
}
register(username, password) { class LoginService:
if (this.users.has(username)) { def __init__(self):
throw new Error('User already exists'); self.users = {}
}
this.users.set(username, { password, createdAt: new Date() });
return true;
}
}
module.exports = LoginService; def register(self, username, password):
if username in self.users:
raise ValueError('User already exists')
self.users[username] = {'password': password, 'created_at': datetime.now()}
return True
"@ "@
Set-Content -Path "login.js" -Value $loginInitial Set-Content -Path "login.py" -Value $loginInitial
git add login.js git add login.py
git commit -m "Start login service implementation" | Out-Null git commit -m "Start login service implementation" | Out-Null
# Add a critical bug to main branch (simulating a bug that was introduced) # Add a critical bug to main branch (simulating a bug that was introduced)
git checkout main | Out-Null git checkout main | Out-Null
$appWithBug = @" $appWithBug = @"
class Application { class Application:
constructor() { def __init__(self):
this.name = 'MyApp'; self.name = 'MyApp'
this.version = '1.0.0'; self.version = '1.0.0'
}
start() { def start(self):
console.log('Application started'); print('Application started')
this.authenticate(); self.authenticate()
}
authenticate() { def authenticate(self):
console.log('Authentication check'); print('Authentication check')
// BUG: This allows unauthenticated access! # BUG: This allows unauthenticated access!
return true; // Should check actual credentials return True # Should check actual credentials
}
}
module.exports = Application;
"@ "@
Set-Content -Path "app.js" -Value $appWithBug Set-Content -Path "app.py" -Value $appWithBug
git add app.js git add app.py
git commit -m "Update authentication (contains bug)" | Out-Null git commit -m "Update authentication (contains bug)" | Out-Null
# Go back to feature branch # Go back to feature branch
@@ -121,35 +105,29 @@ git checkout feature-login | Out-Null
# Create work in progress (uncommitted changes) # Create work in progress (uncommitted changes)
$loginWIP = @" $loginWIP = @"
class LoginService { from datetime import datetime
constructor() {
this.users = new Map();
}
register(username, password) { class LoginService:
if (this.users.has(username)) { def __init__(self):
throw new Error('User already exists'); self.users = {}
}
this.users.set(username, { password, createdAt: new Date() });
return true;
}
// TODO: Complete this method def register(self, username, password):
login(username, password) { if username in self.users:
if (!this.users.has(username)) { raise ValueError('User already exists')
throw new Error('User not found'); self.users[username] = {'password': password, 'created_at': datetime.now()}
} return True
// TODO: Verify password
// TODO: Return user session
}
// TODO: Add logout method # TODO: Complete this method
} def login(self, username, password):
if username not in self.users:
raise ValueError('User not found')
# TODO: Verify password
# TODO: Return user session
module.exports = LoginService; # TODO: Add logout method
"@ "@
Set-Content -Path "login.js" -Value $loginWIP Set-Content -Path "login.py" -Value $loginWIP
# Don't commit - leave as uncommitted changes # Don't commit - leave as uncommitted changes
@@ -169,10 +147,10 @@ Write-Host "1. Navigate to the challenge directory: cd challenge" -ForegroundCol
Write-Host "2. Check your status: git status (see uncommitted changes)" -ForegroundColor White Write-Host "2. Check your status: git status (see uncommitted changes)" -ForegroundColor White
Write-Host "3. Stash your work: git stash save 'WIP: login feature'" -ForegroundColor White Write-Host "3. Stash your work: git stash save 'WIP: login feature'" -ForegroundColor White
Write-Host "4. Switch to main: git checkout main" -ForegroundColor White Write-Host "4. Switch to main: git checkout main" -ForegroundColor White
Write-Host "5. Fix the security bug in app.js (remove the comment and fix the auth)" -ForegroundColor White Write-Host "5. Fix the security bug in app.py (remove the comment and fix the auth)" -ForegroundColor White
Write-Host "6. Commit the fix: git add app.js && git commit -m 'Fix critical security bug'" -ForegroundColor White Write-Host "6. Commit the fix: git add app.py && git commit -m 'Fix critical security bug'" -ForegroundColor White
Write-Host "7. Switch back: git checkout feature-login" -ForegroundColor White Write-Host "7. Switch back: git checkout feature-login" -ForegroundColor White
Write-Host "8. Restore your work: git stash pop" -ForegroundColor White Write-Host "8. Restore your work: git stash pop" -ForegroundColor White
Write-Host "9. Complete the TODOs in login.js" -ForegroundColor White Write-Host "9. Complete the TODOs in login.py" -ForegroundColor White
Write-Host "10. Commit your completed feature" -ForegroundColor White Write-Host "10. Commit your completed feature" -ForegroundColor White
Write-Host "`nRun '../verify.ps1' from the challenge directory to check your solution.`n" -ForegroundColor Cyan Write-Host "`nRun '../verify.ps1' from the challenge directory to check your solution.`n" -ForegroundColor Cyan

View File

@@ -66,21 +66,21 @@ if ($mainCommits -notmatch "security bug|Fix.*bug|security fix") {
exit 1 exit 1
} }
# Check that app.js has been fixed # Check that app.py has been fixed
if (-not (Test-Path "app.js")) { if (-not (Test-Path "app.py")) {
Write-Host "[FAIL] app.js not found on main branch." -ForegroundColor Red Write-Host "[FAIL] app.py not found on main branch." -ForegroundColor Red
git checkout feature-login 2>$null | Out-Null git checkout feature-login 2>$null | Out-Null
Set-Location .. Set-Location ..
exit 1 exit 1
} }
$appContent = Get-Content "app.js" -Raw $appContent = Get-Content "app.py" -Raw
# The bug was "return true" in authenticate - it should be fixed now # The bug was "return true" in authenticate - it should be fixed now
# We'll check that the buggy comment is gone or the implementation is improved # We'll check that the buggy comment is gone or the implementation is improved
if ($appContent -match "allows unauthenticated access") { if ($appContent -match "allows unauthenticated access") {
Write-Host "[FAIL] The security bug comment still exists in app.js." -ForegroundColor Red Write-Host "[FAIL] The security bug comment still exists in app.py." -ForegroundColor Red
Write-Host "Hint: Remove the bug from app.js and commit the fix" -ForegroundColor Yellow Write-Host "Hint: Remove the bug from app.py and commit the fix" -ForegroundColor Yellow
git checkout feature-login 2>$null | Out-Null git checkout feature-login 2>$null | Out-Null
Set-Location .. Set-Location ..
exit 1 exit 1
@@ -103,26 +103,26 @@ if ($commitCount -lt 3) {
exit 1 exit 1
} }
# Check that login.js exists # Check that login.py exists
if (-not (Test-Path "login.js")) { if (-not (Test-Path "login.py")) {
Write-Host "[FAIL] login.js not found on feature-login branch." -ForegroundColor Red Write-Host "[FAIL] login.py not found on feature-login branch." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
$loginContent = Get-Content "login.js" -Raw $loginContent = Get-Content "login.py" -Raw
# Check that login method exists and is implemented # Check that login method exists and is implemented
if ($loginContent -notmatch "login\(username, password\)") { if ($loginContent -notmatch "login\(username, password\)") {
Write-Host "[FAIL] login.js should have a login method." -ForegroundColor Red Write-Host "[FAIL] login.py should have a login method." -ForegroundColor Red
Set-Location .. Set-Location ..
exit 1 exit 1
} }
# Check that TODOs are completed (no TODO comments should remain) # Check that TODOs are completed (no TODO comments should remain)
if ($loginContent -match "TODO") { if ($loginContent -match "TODO") {
Write-Host "[FAIL] login.js still contains TODO comments." -ForegroundColor Red Write-Host "[FAIL] login.py still contains TODO comments." -ForegroundColor Red
Write-Host "Hint: Complete all the TODOs in login.js before committing" -ForegroundColor Yellow Write-Host "Hint: Complete all the TODOs in login.py before committing" -ForegroundColor Yellow
Set-Location .. Set-Location ..
exit 1 exit 1
} }
@@ -155,7 +155,7 @@ if ($stashCount -gt 0) {
# Verify the login implementation is complete # Verify the login implementation is complete
if ($loginContent -notmatch "logout|session") { if ($loginContent -notmatch "logout|session") {
Write-Host "[PARTIAL] login.js is missing logout or session functionality." -ForegroundColor Yellow Write-Host "[PARTIAL] login.py is missing logout or session functionality." -ForegroundColor Yellow
Write-Host "Consider adding logout method for a complete implementation" -ForegroundColor Yellow Write-Host "Consider adding logout method for a complete implementation" -ForegroundColor Yellow
# Don't fail - this is just a suggestion # Don't fail - this is just a suggestion
} }

View File

@@ -31,22 +31,17 @@ git config user.email "user@workshop.local" | Out-Null
# Create initial project files # Create initial project files
$app = @" $app = @"
class Application { class Application:
constructor() { def __init__(self):
this.name = 'TeamProject'; self.name = 'TeamProject'
this.version = '1.0.0'; self.version = '1.0.0'
}
start() { def start(self):
console.log('Application started'); print('Application started')
}
}
module.exports = Application;
"@ "@
Set-Content -Path "app.js" -Value $app Set-Content -Path "app.py" -Value $app
git add app.js git add app.py
git commit -m "Initial application" | Out-Null git commit -m "Initial application" | Out-Null
$readme = @" $readme = @"
@@ -63,17 +58,19 @@ git add README.md
git commit -m "Add README" | Out-Null git commit -m "Add README" | Out-Null
$package = @" $package = @"
{ from setuptools import setup
"name": "team-project",
"version": "1.0.0", setup(
"description": "Learning Git remotes", name='team-project',
"main": "app.js" version='1.0.0',
} description='Learning Git remotes',
py_modules=['app'],
)
"@ "@
Set-Content -Path "package.json" -Value $package Set-Content -Path "setup.py" -Value $package
git add package.json git add setup.py
git commit -m "Add package.json" | Out-Null git commit -m "Add setup.py" | Out-Null
# Create the "remote" repository (bare repository) # Create the "remote" repository (bare repository)
Set-Location .. Set-Location ..
@@ -102,18 +99,17 @@ git config user.name "Teammate" 2>>`$null | Out-Null
git config user.email "teammate@workshop.local" 2>>`$null | Out-Null git config user.email "teammate@workshop.local" 2>>`$null | Out-Null
# Make changes to main branch # Make changes to main branch
`$appContent = Get-Content "app.js" -Raw `$appContent = Get-Content "app.py" -Raw
`$updatedApp = `$appContent -replace "start\(\) {", @" `$updatedApp = `$appContent -replace "def start\(self\):", @"
start() { def start(self):
console.log('Starting application...'); print('Starting application...')
this.initialize(); self.initialize()
}
initialize() { def initialize(self):
"@ "@
Set-Content -Path "app.js" -Value `$updatedApp Set-Content -Path "app.py" -Value `$updatedApp
git add app.js 2>>`$null git add app.py 2>>`$null
git commit -m "Add initialization method" 2>>`$null | Out-Null git commit -m "Add initialization method" 2>>`$null | Out-Null
git push origin main 2>>`$null | Out-Null git push origin main 2>>`$null | Out-Null
@@ -140,7 +136,7 @@ Write-Host "1. Navigate to the challenge directory: cd challenge" -ForegroundCol
Write-Host "2. Clone the remote: git clone remote-repo local-repo" -ForegroundColor White Write-Host "2. Clone the remote: git clone remote-repo local-repo" -ForegroundColor White
Write-Host "3. Navigate to your clone: cd local-repo" -ForegroundColor White Write-Host "3. Navigate to your clone: cd local-repo" -ForegroundColor White
Write-Host "4. Create a feature branch: git checkout -b add-feature" -ForegroundColor White Write-Host "4. Create a feature branch: git checkout -b add-feature" -ForegroundColor White
Write-Host "5. Add a new method to app.js (e.g., stop method)" -ForegroundColor White Write-Host "5. Add a new method to app.py (e.g., stop method)" -ForegroundColor White
Write-Host "6. Commit your changes" -ForegroundColor White Write-Host "6. Commit your changes" -ForegroundColor White
Write-Host "7. Push your branch: git push -u origin add-feature" -ForegroundColor White Write-Host "7. Push your branch: git push -u origin add-feature" -ForegroundColor White
Write-Host "8. Go back to challenge directory: cd .." -ForegroundColor White Write-Host "8. Go back to challenge directory: cd .." -ForegroundColor White

View File

@@ -80,7 +80,7 @@ $mainCommitCount = (git rev-list --count main 2>$null)
if ($featureCommitCount -le $mainCommitCount) { if ($featureCommitCount -le $mainCommitCount) {
Write-Host "[FAIL] add-feature branch has no new commits." -ForegroundColor Red Write-Host "[FAIL] add-feature branch has no new commits." -ForegroundColor Red
Write-Host "Hint: Make changes to app.js and commit them on the add-feature branch" -ForegroundColor Yellow Write-Host "Hint: Make changes to app.py and commit them on the add-feature branch" -ForegroundColor Yellow
Set-Location ../.. Set-Location ../..
exit 1 exit 1
} }
@@ -103,20 +103,20 @@ Write-Host "[PASS] Feature branch pushed to remote!" -ForegroundColor Green
Set-Location ../local-repo Set-Location ../local-repo
# Check if app.js has been modified # Check if app.py has been modified
if (-not (Test-Path "app.js")) { if (-not (Test-Path "app.py")) {
Write-Host "[FAIL] app.js not found." -ForegroundColor Red Write-Host "[FAIL] app.py not found." -ForegroundColor Red
Set-Location ../.. Set-Location ../..
exit 1 exit 1
} }
$appContent = Get-Content "app.js" -Raw $appContent = Get-Content "app.py" -Raw
# Check for user's changes (should have added something) # Check for user's changes (should have added something)
$featureCommits = git log --pretty=format:"%s" add-feature 2>$null $featureCommits = git log --pretty=format:"%s" add-feature 2>$null
if (-not ($featureCommits -match "stop|feature|add" -or $appContent -match "stop")) { if (-not ($featureCommits -match "stop|feature|add" -or $appContent -match "stop")) {
Write-Host "[FAIL] No new feature detected in app.js." -ForegroundColor Red Write-Host "[FAIL] No new feature detected in app.py." -ForegroundColor Red
Write-Host "Hint: Add a new method (like 'stop') to app.js and commit it" -ForegroundColor Yellow Write-Host "Hint: Add a new method (like 'stop') to app.py and commit it" -ForegroundColor Yellow
Set-Location ../.. Set-Location ../..
exit 1 exit 1
} }

View File

@@ -31,30 +31,23 @@ git config user.email "user@workshop.local" | Out-Null
# Create initial calculator with a bug # Create initial calculator with a bug
$calculator = @" $calculator = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a + b; return a + b
}
subtract(a, b) { def subtract(self, a, b):
return a - b; return a - b
}
multiply(a, b) { def multiply(self, a, b):
return a * b; return a * b
}
// BUG: No division by zero check! # BUG: No division by zero check!
divide(a, b) { def divide(self, a, b):
return a / b; return a / b
}
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $calculator Set-Content -Path "calculator.py" -Value $calculator
git add calculator.js git add calculator.py
git commit -m "Initial calculator implementation" | Out-Null git commit -m "Initial calculator implementation" | Out-Null
$readme = @" $readme = @"
@@ -78,38 +71,30 @@ git checkout -b feature-advanced-math | Out-Null
# Add work in progress on feature branch # Add work in progress on feature branch
$calculatorWithFeature = @" $calculatorWithFeature = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a + b; return a + b
}
subtract(a, b) { def subtract(self, a, b):
return a - b; return a - b
}
multiply(a, b) { def multiply(self, a, b):
return a * b; return a * b
}
// BUG: No division by zero check! # BUG: No division by zero check!
divide(a, b) { def divide(self, a, b):
return a / b; return a / b
}
// New feature: power function (work in progress) # New feature: power function (work in progress)
power(a, b) { def power(self, a, b):
return Math.pow(a, b); return a ** b
}
// TODO: Add square root function # TODO: Add square root function
// TODO: Add logarithm function # TODO: Add logarithm function
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $calculatorWithFeature Set-Content -Path "calculator.py" -Value $calculatorWithFeature
git add calculator.js git add calculator.py
git commit -m "Add power function (WIP: more math functions coming)" | Out-Null git commit -m "Add power function (WIP: more math functions coming)" | Out-Null
# Return to challenge directory # Return to challenge directory
@@ -128,11 +113,11 @@ Write-Host "`nYour task:" -ForegroundColor Yellow
Write-Host "1. Navigate to main-repo: cd challenge/main-repo" -ForegroundColor White Write-Host "1. Navigate to main-repo: cd challenge/main-repo" -ForegroundColor White
Write-Host "2. Create a worktree: git worktree add ../bugfix-worktree -b bugfix" -ForegroundColor White Write-Host "2. Create a worktree: git worktree add ../bugfix-worktree -b bugfix" -ForegroundColor White
Write-Host "3. Go to worktree: cd ../bugfix-worktree" -ForegroundColor White Write-Host "3. Go to worktree: cd ../bugfix-worktree" -ForegroundColor White
Write-Host "4. Fix the bug in calculator.js:" -ForegroundColor White Write-Host "4. Fix the bug in calculator.py:" -ForegroundColor White
Write-Host " Add a check: if (b === 0) throw new Error('Division by zero');" -ForegroundColor White Write-Host " Add a check: if (b === 0) throw new Error('Division by zero');" -ForegroundColor White
Write-Host "5. Commit the fix: git add . && git commit -m 'Fix divide by zero bug'" -ForegroundColor White Write-Host "5. Commit the fix: git add . && git commit -m 'Fix divide by zero bug'" -ForegroundColor White
Write-Host "6. Return to main-repo: cd ../main-repo" -ForegroundColor White Write-Host "6. Return to main-repo: cd ../main-repo" -ForegroundColor White
Write-Host "7. Complete your feature: Add square root method to calculator.js" -ForegroundColor White Write-Host "7. Complete your feature: Add square root method to calculator.py" -ForegroundColor White
Write-Host "8. Commit: git add . && git commit -m 'Add square root function'" -ForegroundColor White Write-Host "8. Commit: git add . && git commit -m 'Add square root function'" -ForegroundColor White
Write-Host "9. Clean up worktree: git worktree remove ../bugfix-worktree" -ForegroundColor White Write-Host "9. Clean up worktree: git worktree remove ../bugfix-worktree" -ForegroundColor White
Write-Host "`nRun '../verify.ps1' from the challenge directory to check your solution.`n" -ForegroundColor Cyan Write-Host "`nRun '../verify.ps1' from the challenge directory to check your solution.`n" -ForegroundColor Cyan

View File

@@ -55,13 +55,13 @@ Write-Host "[PASS] Bugfix branch exists!" -ForegroundColor Green
# Check bugfix branch for the fix # Check bugfix branch for the fix
git checkout bugfix 2>$null | Out-Null git checkout bugfix 2>$null | Out-Null
if (-not (Test-Path "calculator.js")) { if (-not (Test-Path "calculator.py")) {
Write-Host "[FAIL] calculator.js not found on bugfix branch." -ForegroundColor Red Write-Host "[FAIL] calculator.py not found on bugfix branch." -ForegroundColor Red
Set-Location ../.. Set-Location ../..
exit 1 exit 1
} }
$bugfixCalc = Get-Content "calculator.js" -Raw $bugfixCalc = Get-Content "calculator.py" -Raw
# Check if division by zero check was added # Check if division by zero check was added
if ($bugfixCalc -notmatch "b === 0|b == 0|division by zero|divide by zero") { if ($bugfixCalc -notmatch "b === 0|b == 0|division by zero|divide by zero") {
@@ -85,12 +85,12 @@ Write-Host "[PASS] Bug fixed on bugfix branch!" -ForegroundColor Green
# Check feature branch for continued work # Check feature branch for continued work
git checkout feature-advanced-math 2>$null | Out-Null git checkout feature-advanced-math 2>$null | Out-Null
$featureCalc = Get-Content "calculator.js" -Raw $featureCalc = Get-Content "calculator.py" -Raw
# Check if square root function was added # Check if square root function was added
if ($featureCalc -notmatch "sqrt|squareRoot") { if ($featureCalc -notmatch "sqrt|squareRoot") {
Write-Host "[FAIL] Square root function not found on feature branch." -ForegroundColor Red Write-Host "[FAIL] Square root function not found on feature branch." -ForegroundColor Red
Write-Host "Hint: Add the square root method to calculator.js on feature-advanced-math branch" -ForegroundColor Yellow Write-Host "Hint: Add the square root method to calculator.py on feature-advanced-math branch" -ForegroundColor Yellow
Set-Location ../.. Set-Location ../..
exit 1 exit 1
} }

View File

@@ -27,327 +27,261 @@ git config user.email "user@workshop.local" | Out-Null
# Commit 1: Initial calculator # Commit 1: Initial calculator
$calc1 = @" $calc1 = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a + b; return a + b
}
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $calc1 Set-Content -Path "calculator.py" -Value $calc1
git add calculator.js git add calculator.py
git commit -m "Initial calculator with add function" | Out-Null git commit -m "Initial calculator with add function" | Out-Null
# Commit 2: Add subtract # Commit 2: Add subtract
$calc2 = @" $calc2 = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a + b; return a + b
}
subtract(a, b) { def subtract(self, a, b):
return a - b; return a - b
}
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $calc2 Set-Content -Path "calculator.py" -Value $calc2
git add calculator.js git add calculator.py
git commit -m "Add subtract function" | Out-Null git commit -m "Add subtract function" | Out-Null
# Commit 3: Add multiply # Commit 3: Add multiply
$calc3 = @" $calc3 = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a + b; return a + b
}
subtract(a, b) { def subtract(self, a, b):
return a - b; return a - b
}
multiply(a, b) { def multiply(self, a, b):
return a * b; return a * b
}
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $calc3 Set-Content -Path "calculator.py" -Value $calc3
git add calculator.js git add calculator.py
git commit -m "Add multiply function" | Out-Null git commit -m "Add multiply function" | Out-Null
# Commit 4: Add divide # Commit 4: Add divide
$calc4 = @" $calc4 = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a + b; return a + b
}
subtract(a, b) { def subtract(self, a, b):
return a - b; return a - b
}
multiply(a, b) { def multiply(self, a, b):
return a * b; return a * b
}
divide(a, b) { def divide(self, a, b):
if (b === 0) throw new Error('Division by zero'); if b == 0:
return a / b; raise ValueError('Division by zero')
} return a / b
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $calc4 Set-Content -Path "calculator.py" -Value $calc4
git add calculator.js git add calculator.py
git commit -m "Add divide function" | Out-Null git commit -m "Add divide function" | Out-Null
# Commit 5: Add modulo # Commit 5: Add modulo
$calc5 = @" $calc5 = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a + b; return a + b
}
subtract(a, b) { def subtract(self, a, b):
return a - b; return a - b
}
multiply(a, b) { def multiply(self, a, b):
return a * b; return a * b
}
divide(a, b) { def divide(self, a, b):
if (b === 0) throw new Error('Division by zero'); if b == 0:
return a / b; raise ValueError('Division by zero')
} return a / b
modulo(a, b) { def modulo(self, a, b):
return a % b; return a % b
}
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $calc5 Set-Content -Path "calculator.py" -Value $calc5
git add calculator.js git add calculator.py
git commit -m "Add modulo function" | Out-Null git commit -m "Add modulo function" | Out-Null
# Commit 6: BUG - Introduce error in add function # Commit 6: BUG - Introduce error in add function
$calc6 = @" $calc6 = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a - b; // BUG: Should be a + b return a - b # BUG: Should be a + b
}
subtract(a, b) { def subtract(self, a, b):
return a - b; return a - b
}
multiply(a, b) { def multiply(self, a, b):
return a * b; return a * b
}
divide(a, b) { def divide(self, a, b):
if (b === 0) throw new Error('Division by zero'); if b == 0:
return a / b; raise ValueError('Division by zero')
} return a / b
modulo(a, b) { def modulo(self, a, b):
return a % b; return a % b
}
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $calc6 Set-Content -Path "calculator.py" -Value $calc6
git add calculator.js git add calculator.py
git commit -m "Refactor add function for clarity" | Out-Null git commit -m "Refactor add function for clarity" | Out-Null
# Commit 7: Add power function (bug still exists) # Commit 7: Add power function (bug still exists)
$calc7 = @" $calc7 = @"
class Calculator { class Calculator:
add(a, b) { def add(self, a, b):
return a - b; // BUG: Should be a + b return a - b # BUG: Should be a + b
}
subtract(a, b) { def subtract(self, a, b):
return a - b; return a - b
}
multiply(a, b) { def multiply(self, a, b):
return a * b; return a * b
}
divide(a, b) { def divide(self, a, b):
if (b === 0) throw new Error('Division by zero'); if b == 0:
return a / b; raise ValueError('Division by zero')
} return a / b
modulo(a, b) { def modulo(self, a, b):
return a % b; return a % b
}
power(a, b) { def power(self, a, b):
return Math.pow(a, b); return a ** b
}
}
module.exports = Calculator;
"@ "@
Set-Content -Path "calculator.js" -Value $calc7 Set-Content -Path "calculator.py" -Value $calc7
git add calculator.js git add calculator.py
git commit -m "Add power function" | Out-Null git commit -m "Add power function" | Out-Null
# Commit 8: Add square root # Commit 8: Add square root
$calc8 = @" $calc8 = @"
class Calculator { import math
add(a, b) {
return a - b; // BUG: Should be a + b
}
subtract(a, b) { class Calculator:
return a - b; def add(self, a, b):
} return a - b # BUG: Should be a + b
multiply(a, b) { def subtract(self, a, b):
return a * b; return a - b
}
divide(a, b) { def multiply(self, a, b):
if (b === 0) throw new Error('Division by zero'); return a * b
return a / b;
}
modulo(a, b) { def divide(self, a, b):
return a % b; if b == 0:
} raise ValueError('Division by zero')
return a / b
power(a, b) { def modulo(self, a, b):
return Math.pow(a, b); return a % b
}
sqrt(a) { def power(self, a, b):
return Math.sqrt(a); return a ** b
}
}
module.exports = Calculator; def sqrt(self, a):
return math.sqrt(a)
"@ "@
Set-Content -Path "calculator.js" -Value $calc8 Set-Content -Path "calculator.py" -Value $calc8
git add calculator.js git add calculator.py
git commit -m "Add square root function" | Out-Null git commit -m "Add square root function" | Out-Null
# Commit 9: Add absolute value # Commit 9: Add absolute value
$calc9 = @" $calc9 = @"
class Calculator { import math
add(a, b) {
return a - b; // BUG: Should be a + b
}
subtract(a, b) { class Calculator:
return a - b; def add(self, a, b):
} return a - b # BUG: Should be a + b
multiply(a, b) { def subtract(self, a, b):
return a * b; return a - b
}
divide(a, b) { def multiply(self, a, b):
if (b === 0) throw new Error('Division by zero'); return a * b
return a / b;
}
modulo(a, b) { def divide(self, a, b):
return a % b; if b == 0:
} raise ValueError('Division by zero')
return a / b
power(a, b) { def modulo(self, a, b):
return Math.pow(a, b); return a % b
}
sqrt(a) { def power(self, a, b):
return Math.sqrt(a); return a ** b
}
abs(a) { def sqrt(self, a):
return Math.abs(a); return math.sqrt(a)
}
}
module.exports = Calculator; def abs(self, a):
return abs(a)
"@ "@
Set-Content -Path "calculator.js" -Value $calc9 Set-Content -Path "calculator.py" -Value $calc9
git add calculator.js git add calculator.py
git commit -m "Add absolute value function" | Out-Null git commit -m "Add absolute value function" | Out-Null
# Commit 10: Add max function # Commit 10: Add max function
$calc10 = @" $calc10 = @"
class Calculator { import math
add(a, b) {
return a - b; // BUG: Should be a + b
}
subtract(a, b) { class Calculator:
return a - b; def add(self, a, b):
} return a - b # BUG: Should be a + b
multiply(a, b) { def subtract(self, a, b):
return a * b; return a - b
}
divide(a, b) { def multiply(self, a, b):
if (b === 0) throw new Error('Division by zero'); return a * b
return a / b;
}
modulo(a, b) { def divide(self, a, b):
return a % b; if b == 0:
} raise ValueError('Division by zero')
return a / b
power(a, b) { def modulo(self, a, b):
return Math.pow(a, b); return a % b
}
sqrt(a) { def power(self, a, b):
return Math.sqrt(a); return a ** b
}
abs(a) { def sqrt(self, a):
return Math.abs(a); return math.sqrt(a)
}
max(a, b) { def abs(self, a):
return a > b ? a : b; return abs(a)
}
}
module.exports = Calculator; def max(self, a, b):
return a if a > b else b
"@ "@
Set-Content -Path "calculator.js" -Value $calc10 Set-Content -Path "calculator.py" -Value $calc10
git add calculator.js git add calculator.py
git commit -m "Add max function" | Out-Null git commit -m "Add max function" | Out-Null
# Create a test file # Create a test file
$test = @" $test = @"
const Calculator = require('./calculator.js'); import sys
const calc = new Calculator(); from calculator import Calculator
// Test addition (this will fail due to bug) calc = Calculator()
const result = calc.add(5, 3);
if (result !== 8) {
console.log('FAIL: add(5, 3) returned ' + result + ', expected 8');
process.exit(1);
}
console.log('PASS: All tests passed'); # Test addition (this will fail due to bug)
process.exit(0); result = calc.add(5, 3)
if result != 8:
print(f'FAIL: add(5, 3) returned {result}, expected 8')
sys.exit(1)
print('PASS: All tests passed')
sys.exit(0)
"@ "@
Set-Content -Path "test.js" -Value $test Set-Content -Path "test.py" -Value $test
# Return to module directory # Return to module directory
Set-Location .. Set-Location ..
@@ -363,11 +297,11 @@ Write-Host "Manually checking each commit would be tedious." -ForegroundColor Ye
Write-Host "Use git bisect to find it efficiently!" -ForegroundColor Green Write-Host "Use git bisect to find it efficiently!" -ForegroundColor Green
Write-Host "`nYour task:" -ForegroundColor Yellow Write-Host "`nYour task:" -ForegroundColor Yellow
Write-Host "1. Navigate to the challenge directory: cd challenge" -ForegroundColor White Write-Host "1. Navigate to the challenge directory: cd challenge" -ForegroundColor White
Write-Host "2. Test the bug: node test.js (it will fail)" -ForegroundColor White Write-Host "2. Test the bug: python test.py (it will fail)" -ForegroundColor White
Write-Host "3. Start bisect: git bisect start" -ForegroundColor White Write-Host "3. Start bisect: git bisect start" -ForegroundColor White
Write-Host "4. Mark current as bad: git bisect bad" -ForegroundColor White Write-Host "4. Mark current as bad: git bisect bad" -ForegroundColor White
Write-Host "5. Mark old commit as good: git bisect good HEAD~10" -ForegroundColor White Write-Host "5. Mark old commit as good: git bisect good HEAD~10" -ForegroundColor White
Write-Host "6. Git will checkout a commit - test it: node test.js" -ForegroundColor White Write-Host "6. Git will checkout a commit - test it: python test.py" -ForegroundColor White
Write-Host "7. Mark result: git bisect good (if test passes) or git bisect bad (if it fails)" -ForegroundColor White Write-Host "7. Mark result: git bisect good (if test passes) or git bisect bad (if it fails)" -ForegroundColor White
Write-Host "8. Repeat until Git finds the first bad commit" -ForegroundColor White Write-Host "8. Repeat until Git finds the first bad commit" -ForegroundColor White
Write-Host "9. Note the commit hash" -ForegroundColor White Write-Host "9. Note the commit hash" -ForegroundColor White

View File

@@ -89,7 +89,7 @@ if ($userCommit -ne $actualBadCommit) {
Write-Host " git bisect start" -ForegroundColor White Write-Host " git bisect start" -ForegroundColor White
Write-Host " git bisect bad" -ForegroundColor White Write-Host " git bisect bad" -ForegroundColor White
Write-Host " git bisect good HEAD~10" -ForegroundColor White Write-Host " git bisect good HEAD~10" -ForegroundColor White
Write-Host " # Then test with: node test.js" -ForegroundColor White Write-Host " # Then test with: node test.py" -ForegroundColor White
Write-Host " git bisect good # or bad" -ForegroundColor White Write-Host " git bisect good # or bad" -ForegroundColor White
Set-Location .. Set-Location ..
exit 1 exit 1
@@ -100,7 +100,7 @@ if ($userCommit -ne $actualBadCommit) {
# Verify the commit actually has the bug # Verify the commit actually has the bug
git checkout $actualBadCommit 2>$null | Out-Null git checkout $actualBadCommit 2>$null | Out-Null
$calcContent = Get-Content "calculator.js" -Raw $calcContent = Get-Content "calculator.py" -Raw
if ($calcContent -notmatch "add\(a, b\)[\s\S]*?return a - b") { if ($calcContent -notmatch "add\(a, b\)[\s\S]*?return a - b") {
Write-Host "[WARNING] The identified commit doesn't seem to have the expected bug." -ForegroundColor Yellow Write-Host "[WARNING] The identified commit doesn't seem to have the expected bug." -ForegroundColor Yellow