5
\$\begingroup\$

In my deployment I need to generate a zip file from a git repo. I have the basic work done with how to pull the latest tag and create the zip file. I ended wanting to update the files that are pulled down to have the last modified of the last commit instead of when I just checked them out.

# Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
param(
    [string] $tag = "",
    [string] $gitURI = "https://github.com/jquery/jquery.git",
    [string] $checkForNewTagsOnly = "Y" #if yes then it will exit if the folder already exists
)
$Currentlocation = "C:\_Builds"
New-Item -ItemType Directory -Force -Path $Currentlocation

Set-Location $Currentlocation
if( $checkForNewTagsOnly -eq "Y"){
    git clone $gitURI --depth 1 master --single-branch
    Set-Location $Currentlocation\master
    git fetch --tags
    $tag = git describe --tags $(git rev-list --tags --max-count=1)
    $tag = $tag|split-path -leaf
}

if([string]::IsNullOrWhiteSpace($tag)){($tag = Read-Host "Enter the tag")}

if( $checkForNewTagsOnly -eq "Y" -and (Test-path $Currentlocation\$tag)){
    Write-Host "$tag already exists, nothing to do"
    exit
}

New-Item -ItemType Directory -Force -Path $Currentlocation
If (Test-path $Currentlocation\$tag) {Remove-item $Currentlocation\$tag}

Set-Location $Currentlocation
git clone $gitURI --recurse-submodules --single-branch --shallow-submodules --branch $tag $tag
Set-Location $Currentlocation\$tag

Write-Host "$tag checked out, running clean up on $Currentlocation"
Get-ChildItem -filter *test* -Directory -recurse -force | remove-item -force -recurse

$ToDelete = "*.gitignore","*.gitattributes","*.gitmodules"
FOREACH ($Item IN $ToDelete) {
    FOREACH ($File IN (Get-ChildItem -recurse | Where-Object {$_.name -like "$Item"})) {
        $FullName = $File.FullName
        Write-Host "Deleting $FullName" -ForegroundColor Green
        Remove-Item $File.FullName
    }
}

Write-Host "fixing the file dates, since git doesn't keep the dates, let's update it the last commit date"
FOREACH ($File IN (Get-ChildItem -recurse)) {
    $FullName = $File.FullName
    $lastModifiedDate = git log -1 --date=short --format=%cd "$FullName"
    $File.LastWriteTime = $lastModifiedDate
    $File.CreationTime = $lastModifiedDate
}

Get-ChildItem -Include .git -recurse -force | remove-item -force -recurse

Write-Host "$tag cleaned, creating zip file"
If (Test-path $Currentlocation\$tag.zip) {Remove-item $Currentlocation\$tag.zip}

Compress-Archive -Path $Currentlocation\$tag -DestinationPath $Currentlocation\$tag.zip

Write-Host "Good Job, the package is created $tag.zip"
\$\endgroup\$
0

1 Answer 1

2
\$\begingroup\$

You should put [CmdletBinding()] before the param block. This gives you some nice features.

I changed $checkForNewTagsOnly to be of type switch rather than string. You can call the script like this MyScript -checkForNewTagsOnly or MyScript -checkForNewTagsOnly:$false. I think that is better because otherwise how are people supposed to know to supply a "Y" as a parameter?

I made the tag parameter mandatory (Mandatory=$true) so that you won't need to check for it later.

By the way, I think you should start these parameters start with a capital letter. That is the convention.

[CmdletBinding()]
param(
    [Parameter(Mandatory=$true, HelpMessage="Enter the tag.")]
    [string] $tag,
    [string] $gitURI = "https://github.com/jquery/jquery.git",
    [switch] $checkForNewTagsOnly = $true #if yes then it will exit if the folder already exists
)

We use $checkForNewTagsOnly like this now that it is a boolean:

if ($checkForNewTagsOnly) {
    # ...
}

We can get rid of this line altogether now that tag is mandatory:

if([string]::IsNullOrWhiteSpace($tag)){($tag = Read-Host "Enter the tag")}

It's generally better to use Write-Output rather than Write-Host because you can't pipe Write-Host output. You couldn't for instance write it to a log.

Write-Host "$tag checked out, running clean up on $Currentlocation"

Please be consistent with your formatting. Why do you have FOREACH in caps? I find the inconsistency of your formatting in general to be extremely triggering to my OCD. It's best to stick to conventional formatting. That makes it easier for people to read.

FOREACH ($Item IN $ToDelete) {
    FOREACH ($File IN (Get-ChildItem -recurse | Where-Object {$_.name -like "$Item"})) {

-Filter is faster than -Include. I don't know if that's an issue here or not, but it's something to be aware of. You used -Filter earlier, by the way.

Get-ChildItem -Include .git -recurse -force | remove-item -force -recurse
\$\endgroup\$
2
  • \$\begingroup\$ Thank you for the feedback. I'll update my code with those changes, for the differences in the case and using filter, it was probably due to grabbing examples off the internet. \$\endgroup\$ Commented Apr 19, 2018 at 22:52
  • \$\begingroup\$ After starting to implement your recommendations, I ended up not using the mandatory param for tag, mostly so I can have anyone run this and it will build the package for whatever is the latest tag without explicitly having to know the tag to enter. \$\endgroup\$ Commented Apr 20, 2018 at 1:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.