Introducing Delobra – Git Branch Deletion for the Opinionated

Delobra [delete local branches] is a simple shell script for the opinionated Git user that takes care of doing some seasonal branch removal in your repository.

Solving the Problem

It was born out of distaste with the current Git-flow methodology, especially when dealing with the integration of a high volume of branches with multiple developers and development teams.

Under this workflow, once you are finished with a feature branch you are expected to merge it back into develop and delete the branch. Keeping the branch, however, might prove useful if you later want to revisit your code in the same exact context or work out breaking changes that were introduced in one of many recent merges.

In this case, being able to switch over to the branch to view your work without having to search through commit messages or merge commits might feel like a blessing.

One downside to this, however, is that the number of branches in your repo will skyrocket over time, and having to delete them one by one is a notable pain.

This is where Delobra comes in and helps you safely remove your finished work with ease, letting you keep your branches for an easier workflow until it’s time to clean out the house.

What It Does

Delobra’s job is to compile a list of branches to queue for deletion, check in with you, and (with your approval) delete the branches from your repository.

Delobra on the Command-Line

It is based on this one Git command:

git branch --merged develop

It lets Git know that you want to retrieve a list of local branches that have been merged into the develop branch, which you can change if you want to use a different branch as a “merging filter”.

Building upon this command, Delobra then excludes any other named branches in the list via the use of grep:

| grep -v -e develop -e master

You can remove these exclusions by simply removing any of the command segments beginning with the -e option and ending with a name, or add your own exclusions by adding the -e option followed by the name contained by any of your branches.

If you’re using a Git-flow methodology, then Delobra will work for you as you can exclude different branches based on their shared naming structure (i.e. feature, release, hotfix).

Even if you aren’t, you can still delete similarly named groups of branches or customize Delobra to fit your needs.

How To Use It

To run Delobra on your Git repositories:

  1. Copy over the delobra.sh file to your home directory ~.
  2. Open a terminal window (or Git Bash if you’re on Windows) in your Git repository directory.
  3. Run the command ~/delobra.sh.

You can find the delobra.sh file on GitHub.

The Lazy Developer’s Guide to Command Line Building with C#

For many C# developers, building and running a small project or even a single class file usually means having to launch Visual Studio and dealing with the overhead of an IDE and a large boilerplate of project code, making testing and exploration of the language and the .NET framework much less enjoyable than it should be.

But there’s another way. A lazier way. That way is called the command line and it has all the tools you need to make writing and testing your gists, snippets, and mounds of C# code easier than ever.

Developer Command Prompt for VS2015

Included with every installation of Visual Studio, this convenient development shell grants you access to the two following C# command-line utilities:

  • csi – An Interactive C# REPL

    csi

    If all you need is a refresher on how a feature of the language works or to confirm whether some code is valid C# or not, you don’t even need a compiler. You can use csi directly from the command line. It stands for “c sharp interactive” and it is a read-eval-print loop (REPL) program which is designed to facilitate understanding what your code does as you write it.

    Working with csi is pretty intuitive. To start the program, simply enter csi in the Developer Command Prompt.

    You can type an expression without a semi-colon to examine its value or write a block of statements so you can immediately use them.

    Referencing libraries (dlls) for testing is easy with the #r directive, just make sure it’s in your current working directory:

    #r "MyLibrary.dll"

    Speaking of directories, if you intend to use csi and csc frequently you will probably want to change the starting directory of the Developer Command Prompt.

    To do so on Windows, simply navigate to the directory that contains the shortcut for launching the Developer Command Prompt, right click on it, select “Properties”, and edit the “Start in:” field with whatever directory path you like.

    To learn more about how csi can make your time with C# more enjoyable and productive, read the official interactive walkthrough.

  • csc – The C# Compiler

    csc

    Microsoft’s very own C# compiler. It has about all that you could expect from a good compiler, and thanks to C#’s language design around namespaces and assemblies, compiling a few files and libraries across directories into one executable is not hard at all.

    Compiling a file into an executable:
    csc File.cs

    Compiling a file into a custom-named executable:
    csc /out:Named.exe File.csc

    Compiling multiple files (from the current directory and a sub-directory named “lib”) into one executable:
    csc File1.cs File2.cs lib\Library.cs

    Compiling all the files in the current directory (one class file must contain a Main method):
    csc *.cs

    Compiling a file into an executable using a library (dll) reference:
    csc /reference:library.dll File.cs

    Compiling a file into a dynamically linked library:
    csc /target:library File.cs

    Mixing and matching arguments:
    csc /target:library /out:MyLib.dll *.cs

    You can view a list of all csc options here.

Essential Windows Command Prompt Commands

While Window’s Command Prompt console is certainly not the most popular shell around, it is still quite handy to be able to know how to perform some basic user tasks with it. The following commands, along with a decent code editor, are about all you’ll need to work with csc and csi effectively:

  • cls – Clears the console window.
  • dir – Lists available directory files.
  • cd – Changes the current directory path.
  • mdMakes a new folder.
  • rdRemoves files and folders.
  • Ctrl + C – Exit out of the current process.
  • Up/Down keys – Iterate through previous commands.
  • Tab key – Press while typing to receive auto-complete suggestions.

Cross-Platform Building

  • Visual Studio Code with .NET Core

    vsc

    Visual Studio Code (VSC) is an excellent and open-source lightweight alternative to Visual Studio that can be used across Windows, macOS, and Linux. It makes use of .NET Core, which is Microsoft’s open-source version of the .NET Framework. Which means that you can write, run, and share your C# projects with just about anyone.

    VSC offers support for Omnisharp, IntelliSense, NuGet, Git, and other programming languages – making it a great tool for all types of developers.

    The way your C# projects work in VSC is that they are folder-based and not file based. When you want to create a new project, you make a new directory or folder, and then through the Visual Studio Code terminal you can make use of the following commands:

    • Ctrl + ` – Opens the VSC Terminal.
    • dotnet new – Creates a new .NET Core C# project with your launchpoint being a class named Program.cs.
    • dotnet restore – Retrieves NuGet dependencies for your project.
    • dotnet run – Builds and runs your project.

    VSC also has a built-in debugger, which you can run with the F5 key.

    To learn more about how to use Visual Studio Code, watch this lively five-minute tour of the software.

  • Mono with mcs and mono

    mono

    Mono is an open-source and cross-platform implementation of the .NET Framework sponsored by Microsoft. Which means that you have full access to C# and most of the .NET libraries across Windows, macOS, and Linux (among many others).

    In the future you can expect most of the general-purpose code in Mono to be identical to that of the .NET Core Framework, but the result is largely the same: C# code across operating systems and platforms.

    The Mono compiler, mcs, works very similarly to csc:

    Compiling a file into an executable:
    mcs File.cs

    Compiling a file into a custom-named executable:
    mcs -out:Named.exe File.csc

    Compiling multiple files (from the current directory and a sub-directory named “lib”) into one executable:
    mcs File1.cs File2.cs lib/Library.cs

    Compiling all the files in the current directory (one class file must contain a Main method):
    mcs *.cs

    Compiling a file into an executable using a library (dll) reference:
    mcs -r:library.dll File.cs

    Compiling a file into a dynamically linked library:
    mcs -target:library File.cs

    Mixing and matching arguments:
    mcs -target:library -out:MyLib.dll *.cs

    Compiling using non-cross platform Windows dlls:
    mcs -out:winforms.exe -r:System.Windows.Forms.dll -r:System.Drawing.dll *.cs

    You can view a list of all mcs options here.

    To run the executable, use mono itself:

    mono File.exe

C# as a Scripting Language with scriptcs and csi

scriptcs

Not many people know this, but you can use C# as a perfectly legitimate scripting language using an open-source and cross-platform program called scriptcs, as well as Microsoft’s csi.

To make a new C# script, simply create a .csx file and directly start writing your code as if you were inside a method or an object.

scriptcs has support for NuGet packages, while csi does not. So the choice of either depends on whether you need to use NuGet or not and whether you’re on Windows or not.

To run a C# script, simply use the following commands:

  • With scriptcs – scriptcs File.csx
  • With csi – csi File.csx

And there you have it, a brand new way to use one of the better object-oriented languages, along with five different command-line tools for interacting with your C# code and making things a little easier.

Making a 4chan Twitter Bot with Groovy in 8 Easy Steps

First off, if you’re reading this you’re probably already wondering: why would anyone want to make such a thing?

“Just what is wrong with you?” might be one of the thoughts racing through your head right now. And I understand, but I’ll ask you to suspend your disbelief if only for a minute and indulge me for one moment.

I Promise I’m Not Evil

As it stands, 4chan is one of the most unique places on the Internet, with a long and rich history of angst-fueled mischief, wildly irreverent humor, unabashedly offensive locker-room banter, the occasional problem with law enforcement, and much, much more.

However, more importantly, I believe it has also acted as an incubator for mainstream Internet culture, providing us with countless memes, phrases, and attitudes that either directly or indirectly shape the sort of behavior we can expect to find both online and offline.

Therefore, and especially for those of us with a fascination for culture, wouldn’t it be interesting to reach into the “brain” of this dynamic, anonymous hive mind and grab just one momentary thought?

Wouldn’t it be worth it to sift through all the erratic noise to find one genuinely thought-provoking gem of commentary? Or… at least, a sincerely silly one!

That’s where the idea for this project came from.

And if you just want to see the real-life application of it, hop on over to Twitter to take a look at @r9k_b, a 4chan Twitter Bot that runs on this very same source code to tweet original user-content from 4chan’s /r9k/ board.

Getting Started

Now, without further ado, let’s dive into the code. With this, you’ll be able to make your own Twitter Bot to pull tweetable commentary from any 4chan board you’re interested in.

You’ll be using the Groovy programming language to write a simple .groovy one-off script. If you already know Java, you basically already know Groovy. If not, now might be a great time to get familiar with it.

Groovy is extremely fun, flexible, and productive to use. Plus, it will grant you access to the entire Java ecosystem of tools and libraries.

If you’re not interested in the process of building the bot, you can go on ahead and view the complete source code directly at the r9k_b GitHub repo.

What You’ll Need

  1. An Installation of the JDK and the Groovy SDK
  2. A Twitter Account
  3. The 4chan API
  4. The Jsoup Library
  5. The Twitter4j Library

First Things First

Before you attempt to proceed with making a Twitter Bot, you first need to register for Twitter’s API. Make sure your account has a valid phone number (for account activation) associated with it, otherwise you will not be able to use it as a bot.

To achieve this you must:

  1. Visit the Twitter Apps page.
  2. Navigate and click on the “Create New App” button.
  3. Complete the application form.
  4. Move on with the “Create Your Twitter Application” button.
  5. Go to the tab that reads “Keys and Access Tokens”
  6. Click on “Create My Access Tokens” at the bottom.

Now, take note of the following:

  • The Consumer Key (API Key)
  • The Consumer Secret (API Secret)
  • The Access Token
  • The Access Token Secret

With these values on hand, create a twitter4j.properties file in the same directory as your Groovy script. Paste in the following code in the file and fill out the values with your own:

oauth.consumerKey=Your_Consumer_Key
oauth.consumerSecret=Your_Consumer_Secret
oauth.accessToken=Your_Access_Token
oauth.accessTokenSecret=Your_Access_Token_Secret

What You’ll Be Doing

  1. Using Grape annotations to quickly and easily add your library dependencies to your script.
  2. Making a 4chan API request for the catalog of active threads in a board of your choosing.
  3. Parsing the JSON response.
  4. Iterating over the catalog in order to store the thread IDs for future retrieval of each thread’s user posts.
  5. Making another 4chan API request for each of the stored threads.
  6. Parsing the JSON response.
  7. Iterating over each of the parsed threads in order to store the “tweetable” (length <= 140) user posts/comments.
  8. Picking and tweeting a stored user comment to your account.

Step 1: Adding Imports and Dependencies

This code snippet contains all you need to get started with writing the actual code in your script. It uses Grape to fetch the .jar files for you, so you don't have to worry about dependency management and you can focus on writing your code:

import groovy.json.JsonSlurper
import java.net.URL
import java.text.SimpleDateFormat

@Grab(group='org.twitter4j', module='twitter4j-core', version='4.0.5')
import twitter4j.Status
import twitter4j.Twitter
import twitter4j.TwitterException
import twitter4j.TwitterFactory

@Grab(group='org.jsoup', module='jsoup', version='1.9.2')
import org.jsoup.Jsoup

Steps 2-4: Retrieving Catalog and Thread Board Data

These steps require some underlying knowledge of the 4chan API and the intuitive Groovy JsonSlurper class. It is worth mentioning that the left shift operator is overloaded to support addition of elements into a List object.

As implied in the beginning, this example will use the /r9k/ board as a data source.

final String BOARD_NAME = "/r9k/"
final String THREAD_CATALOG_REQUEST_URL = "https://a.4cdn.org" + BOARD_NAME + "threads.json"

println "Retrieving " + BOARD_NAME + " data..."

threadCatalogData = new URL(THREAD_CATALOG_REQUEST_URL).getText() // Makes the HTTP request.
List threadCatalog = new JsonSlurper().parseText(threadCatalogData) // Parses JSONObjects into Maps and JSONArrays into Lists.

// Store all active threads from the board.
listOfThreads = []
numOfPages = threadCatalog.size()
numOfPages.times { i ->
    Map catalogPage = threadCatalog.get(i)
    List threadsInPage = catalogPage.threads
    numOfThreadsInPage = threadsInPage.size()
    numOfThreadsInPage.times { j -> listOfThreads << threadsInPage.get(j).no }
}

Steps 5-7: Retrieving Tweetable User Comments

These steps are very similar to the previous three. Additionally, you will be using a different method to loop for a specified number of iterations. You can find out more about these and other methods used to loop over stuff in the Groovy language here.

listOfComments = []

// Retrieve all posts from 20% of the most recent threads in the board catalog.
1.upto(listOfThreads.size() / 5) { i ->
    chosenThreadNo = listOfThreads.get(i)
    threadPageRequestUrl = "https://a.4cdn.org" + BOARD_NAME + "thread/" + 
        chosenThreadNo + ".json"

    threadPageData = new URL(threadPageRequestUrl).getText()
    Map threadPage = new JsonSlurper().parseText(threadPageData)

    List posts = threadPage.posts

    // Grab all the thread comments of Twitter-able length (with no URLs or web links).
    final int CHARACTER_LENGTH = 140
    numOfPosts = posts.size()
    numOfPosts.times { j ->
        Map post = posts.get(j)
        if (post.com != null) {
            comment = Jsoup.parse(post.com).text() // Removes HTML from comment.
            if (comment.length() <= CHARACTER_LENGTH && !comment.contains("www") 
                && !comment.contains("http"))
                listOfComments << comment
        }
    }

    Thread.sleep(2000) // Respect the 4chan API rules.
}

Step 8: Posting the Tweet

// Choose a comment for Twitter posting.
    chosenCommentIndex = new Random().nextInt(listOfComments.size())
    chosenComment = listOfComments.get(chosenCommentIndex)

    twitter = TwitterFactory.getSingleton()
    twitter.updateStatus(chosenComment)

    Date date = new Date()
    SimpleDateFormat today = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")
    println today.format(date) + " - Updated Twitter status with: " + chosenComment

    // Wait for a while (15 mins) until the next tweet.
    Thread.sleep(900000)

Final Step: Putting It All Together

To finish off the script, we wrap all the code logic inside a while loop that continually executes until we decide to close down the console:

import groovy.json.JsonSlurper
import java.net.URL
import java.text.SimpleDateFormat

@Grab(group='org.twitter4j', module='twitter4j-core', version='4.0.5')
import twitter4j.Status
import twitter4j.Twitter
import twitter4j.TwitterException
import twitter4j.TwitterFactory

@Grab(group='org.jsoup', module='jsoup', version='1.9.2')
import org.jsoup.Jsoup

while(true) {
    final String BOARD_NAME = "/r9k/"
    final String THREAD_CATALOG_REQUEST_URL = "https://a.4cdn.org" + BOARD_NAME + "threads.json"

    println "Retrieving " + BOARD_NAME + " data..."

    threadCatalogData = new URL(THREAD_CATALOG_REQUEST_URL).getText() // Makes the HTTP request.
    List threadCatalog = new JsonSlurper().parseText(threadCatalogData) // Parses JSONObjects into Maps and JSONArrays into Lists.

    // Store all active threads from the board.
    listOfThreads = []
    numOfPages = threadCatalog.size()
    numOfPages.times { i ->
        Map catalogPage = threadCatalog.get(i)
        List threadsInPage = catalogPage.threads
        numOfThreadsInPage = threadsInPage.size()
        numOfThreadsInPage.times { j -> listOfThreads << threadsInPage.get(j).no }
    }

    listOfComments = []

    // Retrieve all posts from 20% of the most recent threads in the board catalog.
    1.upto(listOfThreads.size() / 5) { i ->
        chosenThreadNo = listOfThreads.get(i)
        threadPageRequestUrl = "https://a.4cdn.org" + BOARD_NAME + "thread/" + 
            chosenThreadNo + ".json"

        threadPageData = new URL(threadPageRequestUrl).getText()
        Map threadPage = new JsonSlurper().parseText(threadPageData)

        List posts = threadPage.posts

        // Grab all the thread comments of Twitter-able length (with no URLs or web links).
        final int CHARACTER_LENGTH = 140
        numOfPosts = posts.size()
        numOfPosts.times { j ->
            Map post = posts.get(j)
            if (post.com != null) {
                comment = Jsoup.parse(post.com).text() // Removes HTML from comment.
                if (comment.length() <= CHARACTER_LENGTH && !comment.contains("www") 
                    && !comment.contains("http"))
                    listOfComments << comment
            }
        }

        Thread.sleep(2000) // Respect the 4chan API rules.
    }

    // Choose a comment for Twitter posting.
    chosenCommentIndex = new Random().nextInt(listOfComments.size())
    chosenComment = listOfComments.get(chosenCommentIndex)

    twitter = TwitterFactory.getSingleton()
    twitter.updateStatus(chosenComment)

    Date date = new Date()
    SimpleDateFormat today = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")
    println today.format(date) + " - Updated Twitter status with: " + chosenComment

    // Wait for a while (15 mins) until the next tweet.
    Thread.sleep(900000)
}

Now that you've got the whole script, save it (if you haven't already) as filename.groovy. You can execute it with a groovy filename command or simply give it a double click to run if you installed the Groovy SDK properly.

Congratulations! You now have your very own operational 4chan Twitter Bot.

Now sit back, run the script, and be prepared to be made very uncomfortable, repeatedly.

Update: The original r9k_b script has been Groovy'fied by none other than GR8Conf founder Søren Berg Glasius. You can view the updated script over in the main branch of the r9k_b repo.