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"
1 Answer 1
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
-
\$\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\$Josh Knutson– Josh Knutson2018年04月19日 22:52:46 +00:00Commented 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\$Josh Knutson– Josh Knutson2018年04月20日 01:03:30 +00:00Commented Apr 20, 2018 at 1:03