Creating Local Git Repositories – Yeah, it’s that simple!
We’re in the process of evaluating several source control systems here at the office. It’s a JOYOUS experience and I mean that… sorta. Currently, we have a montage of files dumped into two SourceSafe repos.
At this point, most of you are either laughing, crying, or have closed your web browser so you don’t get caught reading something with the word ‘SourceSafe’ in it. That’s cool, I get that.
As part of my demonstrations (for the various toolings we’re looking at), I wanted to show how simple it was to create a local GIT repository.
Since I’m discussing ‘local’, I’m taking a lot of things out of the picture.
-
Authentication/authorization is handled by Windows file permissions/Active Directory. If you can touch the repo and read it, then knock yourself out.
-
Everything is handled through shares, no HTTP or that goodness. Users are used to hitting a mapped drive for SourceSafe repos, we’re just emulating that.
So what do we need to do to create a Git repository? Three easy steps (commands).
1. Create your directory with the .git extention.
mkdir example.git
2. Change into that new directory.
cd example.git
3. Initialize the repository using Git.
Our new Git repository is now initialized. You can even see that PowerShell picks up on the new repository and has changed my prompt accordingly.
Now that we have example.git as our ‘remote’ repository, we’re ready to make a local clone.
git clone H:\example.git example
Now we have an empty clone (and it’s kind enough to tell us).
All of our Git goodness is packed into the standard .git directory.
To test things out, let’s create a quick file, add it to our repo, and then commit it in.
First, let’s create/append an example file in our clone.
(note: this is called ‘so lazy, I don’t even want to open NotePad’)
Now, we can add and verify that our newly added ‘example.text’ file shows up:
Finally, commit…
git commit -a -m “this is our first commit”
… and push!
git push origin master
The last step is to ensure that our new ‘remote’ repository can be reproduced. Here’s a quick single line to clone our repository into another new folder, list out the contents, and verify the log has the commit we made in the first repo.
It’s amazing how quick and easy it is to setup local Git repositories. From here, we can look at the file system/Windows for authentication/authorization and focus on our migration AWAY from Visual SourceSafe.
PowerShell: Recreating SQL*Plus ‘ed’ Command
Aside from PowerShell, I spend a bit of time day-to-day in Oracle’s SQL*Plus. I’m slowly replacing my dependency on SQL*Plus with PowerShell scripts, functions, and such, but there are some core things that it’s just easier to bring up a console and hack out.
One thing I really love about SQL*Plus is the ‘ed’ command. The ‘ed’ command dumps your last statement into a temp file, then opens it in Notepad. Make your changes in Notepad, save, and rerun (in SQL*Plus, it’s a single slash and then Enter), and the frustration of lengthy command line editing is solved.
So, this is a work in progress—my attempt to simulate the same process in PowerShell.
Example Situation
Let’s say, for example, we have a long command we have been hacking away at, but are getting tired of arrowing back and forth on:
$count = 0; sq mydb “select id from reports” | % { $count++ }; $count
(Yes, yes, it’s not ‘very long’, but that’s why this is called an example!)
So, a simple row counter.
The ‘ed’ Command
To recreate the ‘ed’ experience, I need two things:
- Access to the command line history via get-history.
- A temporary file.
touch c:\temp.tmp
get-history | ?{ $_.commandline -ne “ex” } |
? { $_.commandline -ne “ed” } |
select commandline -last 1 |
%{ $_.CommandLine} > c:\temp.tmp
np c:\temp.tmp
Stepping through the code:
- Create a temporary file. I used c:\temp.tmp, but you could get a bit fancier and use the systems $TEMP directory or something.
- Get-History. This returns an ascending list of your command history in PowerShell by ID and CommandLine. We want to ignore any calls to our ‘ed’ or ‘ex’ functions and grab the “last 1”—then insert it into our temp file.
- Finally, open up the temp file in NotePad (np is an alias on my PowerShell profile for NotePad2).
So now that I have my ed command, let’s try it out after I’ve already ran my simple row counter.
Cool. We can now make changes to this and SAVE the temp file. The next step would be to jump back to PowerShell and execute the updated command.
The ‘ex’ Command
Since the slash has special meaning in a PowerShell window, I simply named this script ‘ex’ instead. Ex… execute… surely I can’t forget that, right?
get-content c:\temp.tmp |
% {
$_
invoke-expression $_
}
The ‘ex’ command is pretty simple.
-
Get the content of our temporary file from get-content.
-
For each line (since get-content returns an array of lines), print out the line as text and then invoke (run) it using invoke-expression.
Invoke-Expression takes a string as a command (from our text file) and returns the results. For more information on Invoke-Expression, check out MSDN.
Wrapping It Up
Now that we have our two commands—ed and ex—we’re ready for those “oh, this is short and easy” commands that turn into multi-page monsters—without fighting tabs and arrow keys.
As I said, this is a work-in-progress. I’ll update the post as new/better ideas come up.
PowerShell : TGIF Reminder
Jeff Hicks’ TGIF post yesterday was a fun way to learn a bit of PowerShell (casting, working with dates, etc) and also add something valuable to your professional toolbelt—knowing when to go home.
I tweaked the date output a bit to be more human readable, but also moved it from just a function to part of my UI. I mean, I should ALWAYS know how close I am to quittin’ time, right? Especially as we joke around our office during our ‘payless weeks’.
# Determines if today is the end of friday! (fun function)
function get-tgif {
$now=Get-Date
# If it’s Saturday or Sunday then Stop! It’s the weekend!
if ([int]$now.DayOfWeek -eq 6 -or [int]$now.DayOfWeek -eq 7)
{
”Weekend!”
}
else {
# Determine when the next quittin’ time is…
[datetime]$TGIF=”{0:MM/dd/yyyy} 4:30:00 PM” -f `
(($now.AddDays( 5 – [int]$now.DayOfWeek)) )
# Must be Friday, but after quittin’ time, GO HOME!
if ((get-date) -ge $TGIF) {
”TGIF has started without you!”
}
else {
# Awww, still at work–how long until
# it’s time to go to the pub?
$diff = $($tgif – (get-date))
”TGIF: $($diff.Days)d $($diff.Hours)h $($diff.Minutes)m”
}
}
}
NOTE: My “end time” is set to 4:30PM, not 5:00PM—since that’s when I escape. Change as necessary.
The code comments explain most of it. As you can see, I added in one more check—let me know when it’s simply the weekend. I also removed the Write-Host calls, since I simply want to return a String from the function. I could use the function, as necessary, with formatting, and add it to other scripts and such. For example:
Write-Host $(get-tgif) -fore red
The next step was tapping into the $Host variable. Since I use Console2, my PowerShell window is a tab rather than the whole window. Console2 is aware of PowerShell’s $Host.UI methods and adheres to the changes.
To add get-tgif to my prompt’s window title:
$windowTitle = “(” + $(get-tgif) + “) “
$host.ui.rawui.WindowTitle = $windowTitle
Easy enough. Now my window title looks like (ignore the path in there for now):
But that only sets it when you log in… and I want to update it (and keep that path updated as I traverse through directories). To do that add a function called ‘prompt’ to your PowerShell Profile. Prompt is processed every time the “PS>” is generated and allows you a great deal of customization. See the post here for further details on how I’ve customized my prompt to handle Git repositories.
So, move those two lines into our prompt function, and our TGIF timer now updates every time our prompt changes… keeping it pretty close to real time as you work.
function prompt {
$windowTitle = “(” + $(get-tgif) + “) ” + $(get-location).ToString()
$host.ui.rawui.WindowTitle = $windowTitle[…]
}
This could be tweaked to any type of countdown. I’m sure a few of those around the office would have fun adding retirement countdowns, etc.
Happy TGIF!
PowerShell : Add Recursive Directories to PATH
As I continue to go script crazy (a bit) with PowerShell, I’ve noticed that my general scripts directory has grown quite a bit and is becoming a bit unmanagable. Being a lover of neat and tidy, I wanted to separate ‘common’ scripts from ‘server-based’ and ‘task’ scripts.
Sounds easy enough, but that breaks part of my PowerShell profile—the part where I add the scripts directory to the path. Moving those files out of that directory, even if they’re in subdirectories, would take them out of the path and I’d lose my [a..b]-{tab} goodness.
So, how to add the recursive structure to PATH?
It’s easy!
In my Profile, $scripts is a variable that contains a path to my ‘standard’ scripts directory based on whatever computer I’m currently logged into.
From there, simply use the built-in features of PowerShell.
gci $scripts |
? { $_.psIsContainer } |
% { [System.Environment]::SetEnvironmentVariable(“PATH”,
$Env:Path + “;” + $_.FullName, “Process”) }
Verbatim: for each child object in $scripts that is a container, append the full name to PATH.
Exactly what I wanted and works like a champ. Now I can move my scripts around, create new directories, the works—and each time I restart my console, it’ll detect the new directories and simply work—exactly like a shell should.
Updated: PowerShell “Code-Cat” With Colors and Line Breaks
Motivated by Jeffery Hicks’ fun with my original “code-cat” version, I decided to fill in a few of the original updates I had floating in my head.
The full code is available here via CodePaste.Net.
First off, I loved the idea of colorizing the comments in a file; however, I wanted to keep my line numbers out of the “coloring” and simply color the comments. To do this, I had to break apart the line numbers from the actual output.
Second, I really wanted a cleaner way to wrap lines in my code and to have those lines still lineup with everything else.
The full code is available via CodePaste.Net (click here), but let’s step through it and see how things work.
SplitString Function
You’ll notice at the top, I’ve included a custom helper function that takes a string and splits it into an array. I use this to break up “long” strings into window-sized strings.
function splitString([string]$string, [int]$length)
{
$lines = @();
$stringLength = $string.Length;
$position = 0;while ($position -lt $stringLength)
{
if (($position + $length) -lt $stringLength)
{
$lines += $string.substring($position, $length);
}
else
{
$lines += $string.substring($position);
}
$position += $length;
}return $lines;
}
This method is actually in my PowerShell profile for use in numerous parsing activities.
Colors and Window Size
Unlike the original method, I’ve pulled out the colors into variables so they are easily configured. I am also using the built-in PowerShell $Host object to determine the width of my console window. I’ll use this later for the line breaks.
$codeColor = “Gray”;
$counterColor = “White”;
$commentColor = “Green”;
$newLineColor = “Yellow”;# Window size, minus the counter, spacing, and a bit extra padding.
$maxLineSize = $Host.UI.RawUI.WindowSize.Width – 12;
Parsing The Code File
There are a few important points in the $content body, here we go!
Replacing Tabs With Spaces
I found that the Substring and Length functions got really quirkly (is a tab 1 character or five, etc) when they came across several tabs (which, tabbing is pretty common in a code file, especially some SQL files). To remedy this, I replace tabs with five spaces. This also allows me to control the tabs a bit more, so if I wanted to ease my code output to the left, I could use three or four spaces.
# remove tabs, they’re counted as one character, not five.
$currentLine = $_.Replace(“`t”, “ “);
Setting the Color of Comments
Using Jeffery’s example, I’m also setting my comments (for PowerShell, C#, and TSQL) to a bright color.
# Color-code comments green (PowerShell, C#, SQL)
if ($currentLine.Trim().StartsWith(“#”) -or `
$currentLine.Trim().StartsWith(“//”) -or `
$currentLine.Trim().StartsWith(“–”))
{
$foregroundColor = $commentColor;
}
Separating Line Numbers From Content
I didn’t want my line numbers to show up green for comments and I wanted to treat them with a different color than the rest of the code body, so I’m taking advantage of the “-nonewline” feature of write-host. This returns the content without forcing a new line break into the result. Very handy.
write-host (“{0:d4} | ” -f $counter) -nonewline -foregroundColor $counterColor;
Checking for Line Breaks and Handling Them
The next bit is in “beta” for the time being. The gist is that it looks at the length of the current line vs. the maximum line size we specified in the variables.
If the current line is longer, it breaks the line into an array of “max line size” lines. The first line is output using our normal methods—we want our counter to show up, right? The ‘overflow’ lines are output using a fancy arrow “\—>” and do not include a counter—simply because they are not ‘new lines’.
Of course, if our line is shorter than our window size, it is simply output.
if ($currentLine.Length -ge $maxLineSize)
{
$splitLines = splitString $currentLine $maxLineSize;
$countOfLines = $splitLines.Length;
for ($i = 0; $i -lt $countOfLines; $i++)
{
if ($i -eq 0)
{
# our first line doesn’t look any different.
write-host (“{0}” -f $splitLines[$i]) -foregroundColor $foregroundColor;
}
else
{
# next lines are using the fancy arrow.
write-host (“\–> | “) -nonewline -foregroundColor $newLineColor;
write-host (“{0}`n” -f $splitLines[$i]) -nonewline -foregroundColor $foregroundColor;
}
}
}
else
{
write-host (“{0}” -f $_) -foregroundColor $foregroundColor;
}
Again, the full code is available here via CodePaste.Net.
Like all things, a work in progress!
PowerShell – Easy Line Numbers using Cat (Get-Content)
I often cat out code pages from the prompt when I simply want to see what’s inside or look for a method. Cat, of course, is an alias to PowerShell’s get-content cmdlet, but cat brings me back to days in Unix and makes me feel better.
One thing that was a bit of a trouble was looking for a specific line of code.
For example: Looking through the debug logs, I see an error occuring at line 40 of some file. That’s great, but who wants to count lines? Instead, we open up Visual Studio and look. Well, that’s a hassle too.
Here’s a quick script that does a simple line count with the line in the file.
param ([string] $filename)
$counter = 0;
$content = get-content $filename |
% { $counter++; write-host “$counter`t| $_” }
Since the result of get-content becomes an enumerable line-by-line list, it’s easy to iterate through and increment a counter.
To call it, just call the method with the file name. For mine, I called it cat-code.ps1, though I’ll probably set an alias to ‘cc’ or something later on.
.\cat-code.ps1 psake_default.ps1
From here, you could add in a check to the $Host.UI.RawUI and handle the overflows a bit better, but that’s for another day!
Reusable ‘Controls’ with Sprites, CSS, and Spark Partials
I came across SilkSprite during some of my work with BluePrintCSS and fell in love. I’ve used the FamFamSilk icons for ages and, with a current project, wanted to implement some instant CSS buttons and menu items using those icons.
So, with CSS-fu in hand, here’s how the button turned out.
First, creating a simple CSS button style:
.button
{
display: inline-block;
font-weight: bold;
font: bold .85em/2.5em Verdana, Helvetica, sans-serif;
text-decoration: none;
text-indent: 10px;
width: 150px;
height: 2.5em;
color: #555555;
background-color: #EAEAD7;
border: #CCCCCC solid 1px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
}
.button:hover
{
background-color: #F3F3E9;
color: #737373;
cursor: pointer;
}
This button is pretty simple and standard—nothing fancy. The most important tag in there is display: inline-block as this allows our buttons to share the same row and not stack on top of each other (like float:left would cause).
Hover Off:
Hover On:
Second, because I needed to include the icon INSIDE another container (the button), I modified the original SilkSprite ss_sprite and removed a bit of the extra padding.
.sprite
{
display: inline-block;
overflow: hidden;
background-repeat: no-repeat;
background-image: url(/content/img/sprites.png);
padding-left: 25px;
padding-top: 2px;
height: 16px;
max-height: 16px;
vertical-align: middle;
}
The important thing to note here is the padding-top and the height attributes. Until I’m lead into the light and improve my CSS-fu, I’m compensating for the font height differences by using padding-top. e.g. I want the icon to truly show up in the “middle”… and vertical-align just wasn’t pushing it far enough.
We’ll come back to actually working with SilkSprite in a moment, let’s work up a quick Spark partial view to display our results. Now, you could do this without the partial views—just replace my Spark variables with the actual text we’re passing to them. I’ll provide both examples.
Our button needs three elements to be useful:
- An ID so that we can call it from jQuery or your client-side query engine of choice,
- A Sprite Name, such as ss_add, etc. These are provided by SilkSprite.
- The button text.
So, knowing that, a basic button could be rendered using:
<div id=”my-button” class=”button”>
<span class=”sprite ss_add” />Add Activity
</div>
We can simply substitute out the variable elements (id, sprite class, and text) and create a Spark partial view (named _styledButton.spark and located in the /Shared view folder).
<div id=”${id}” class=”button”>
<span class=”sprite ${sprite}“></span>${text}
</div>
In our views, it’s easy to create a button:
<styledButton text=”‘Add Activity‘” id=”‘my-button‘” sprite=”‘ss_page_add‘” />
Note: You need to surround your text with single quotes (‘text’) to inform the Spark engine that the information contained in your variables is a string.
Now, we have shiny, icon’d buttons:
Hover Off:
Hover On:
Automating Extracts Using External .SQL Files and PowerShell
Rather than rely on a system task, I wanted to be able to kick off an export of one of our SQL databases on the fly, have it generate a CSV, then email the CSV to one of our developers.
Sounds like a task for PowerShell!
Why PowerShell? Well, frankly, because moving jobs around and such on our mixed-mash of SQL versions and servers is a bit annoying and I wanted to see if it worked.
So, to start off, I have a file, call it export_data.sql that contains all of the logic of my SQL query and the format I require.
I’ll also be using the Microsoft SQL query script I discussed in this blog post.
The tricky part is reading in the .sql file as a single “entity”—not the array of rows that get-content usually provides. Thankfully, there is an easy way to do it.
@(gc ‘export_data.sql’ -readcount 0)
According to the PowerShell documentation, the readcount parameter serves two purposes: one is to set the number of lines to read at a time, the second (when set to zero) is to pull in all of the lines at once. Great, that’s exactly what we need.
From there, it’s simply feeding our query to the sql-query function I wrote and exporting to CSV. Nice enough, CSV exports are built-in to PowerShell!
The final command looks something like this:
@(gc ‘export_data.sql’ -readcount 0) |
% { sql-query server db $_ } |
export-csv dump.csv
I could then add another field to mail the csv using the built-in command Send-MailMessage.
<3 PowerShell.
Populating Select Lists in ASP.NET MVC and jQuery
I’ve been working the last bit to find the best way to create/populate select (option) lists using a mixture of ASP.NET MVC and jQuery. What I’ve run into is that the “key” and “value” tags are not passed along when using Json(data).
Here’s what I’m trying to pull off in jQuery: building a simple select drop down list.
var dd_activities = “<select id=’dd_activities’>”;
var count = data.length;
for (var i = 0; i < count; i++) {
dd_activities += “<option value=’” + data[i].Key + “‘>” + data[i].Value + “</option>”;
}
dd_activities += “</select>”;$(“#activities”).before(dd_activities);
Using some very basic key/value data:
[
{"3","Text Value"},
{"4","Another Text Value"},
{"1","More boring values..."},
{"2","Running out of values"},
{"5","Last value..."}
]
[Authorize]
[CacheFilter(Duration = 20)]
public ActionResult GetActivitiesList()
{
try
{
var results =
_activityRepository
.GetAll()
.OrderBy(x => x.Target.Name).OrderBy(x => x.Name)
.Select(x => new
{
Key = x.Id.ToString(),
Value = string.Format(“[{0}] {1}”, x.Target.Name, x.Name)
})
.ToList();
return Json(results);
}
catch (Exception ex)
{
return Json(ex.Message);
}
}
[
{"Key":"3","Value":"Text Value"},
{"Key":"4","Value":"Another Text Value"},
{"Key":"1","Value":"More boring values..."},
{"Key":"2","Value":"Running out of values"},
{"Key":"5","Value":"Last value..."}
]
var criteria =
Session.CreateCriteria<Activity>()
.CreateAlias(“Target”, “Target”)
.Add(Restrictions.Eq(“IsValid”, true))
.AddOrder(Order.Asc(“Target.Name”))
.AddOrder(Order.Asc(“Name”))
.SetMaxResults(100);
var data = criteria.List<Activity>();
var result =
data
.Select(x => new
{
Key = x.Id.ToString(),
Value = string.Format(“[{0}] {1}”, x.Target.Name, x.Name)
})
.ToList();
tx.Commit();
return result;
try
{
return Json(_activityRepository.GetActivitiesList());
}
catch (Exception ex)
{
return Json(ex.Message);
}
Html.Grid Rendering as Plain Text?
Notice: Stupid, stupid moment described ahead. Proceed with caution.
I spent a good half hour trying to figure out why my MVCContrib Html.Grid<T> wasn’t rendering. It wasn’t throwing an error, it was simply returning the HTML code as Plain Text.
- The AutoMapper code looked good,
- The Html.Grid<T> code looked good (it’d be templated off another page anyway and that page was working),
- The view model code looked good.
So why was I being greeted with garble junk?
${Html.Grid(Model.Details) .Attributes(Id => “RoutineDetails”) .Columns(column => { column.For(c => this.Button(“EditDetail”).Value(“Edit”).Id(string.Format(“edit_{0}”, c.Id))).DoNotEncode(); column.For(c => c.Activity.Target.Name).Named(“Target Area”); column.For(c => c.Activity.Name).Named(“Activity”); column.For(c => c.Sets); column.For(c => c.Weight); column.For(c => c.Repetitions); column.For(c => c.Duration); })}
Html.Grid that is not… well, at least not properly.
Encoding issue? Maybe. Data issue? Perhaps.
No, the issue was typing too quick and not paying attention.
public ActionResult New()
{
var viewModel = BuildRoutineNewViewModel(new Routine());
return View();
}
Yeah, that’s the problem… right there. I’d forgotten to pass the view model into the View. Apparently the Html.Grid<T> helper simply panics if the model you’re reading from is empty or null—rather than throwing an error.
Oddly enough, this is one of those times I’d wish the screen would have lit up red. Lessons learned.