1. 2017-07-24 - Update Jekyll blog entry meta-data; Tags: Update Jekyll blog entry meta-data
    Loading...

    Update Jekyll blog entry meta-data

    If you track your jekyll post with git, preferably if you hosting your github pages, than you can utilize the git attributes to automatically update post meta-data. For instance we replace the modified information in the yaml frontmatter (that is the jekyll metadata) every time you do a update on a jekyll post or page.

    General Mechanism

    Check Customizing Git - Git Attributes and Customizing Git - Git Hooks to understand the mechanism in detail.

    In short:

    • write a script that replaces the date with current date
    • configure git to call that filter on every commit
    • setup filter for respective jekyll files, i.e. markdown

    Replacing Modified Timestamp

    Before we I configure the git hook, I have to find the appropriate command to do that. Therefore create an example yaml frontmatter.

    >tan@omega:~$ cat test.txt --- layout: post status: publish published: true title: Reindex Watcher Indices with Curator author: tan date: '14.07.2017 10:48' modified: '2017-07-14 16:58:43 +0200' categories: - IT tags: - elasticsearch ---

    Use sed to replace existing field with the new timestamp.

    sed -i "s/modified:.*/modified: \'$(date +'%Y-%m-%d %H:%M:%S %z')\'/" test.txt
    

    Check the modified output

    tan@omega:~$ cat test.txt
    ---
    layout: post
    status: publish
    published: true
    title: Reindex Watcher Indices with Curator
    author: tan
    date: '14.07.2017 10:48'
    modified: '2017-07-25 10:36:08 +0200'
    categories:
    - IT
    tags:
    - elasticsearch
    ---
    

    The git manual has a ruby program example

    tan@omega:~/bin$ cat expand_date 
    #! /usr/bin/env ruby
    data = STDIN.read
    last_date = `git log --pretty=format:"%ad" -1`
    puts data.gsub('$Date$', '$Date: ' + last_date.to_s + '$')
    

    Filters

    It turns out that you can write your own filters for doing substitutions in files on commit/checkout. These are called “clean” and “smudge” filters.

    • smudge - before they’re checked out (on checkout)
    • clean - before they’re staged in (on add)

    The manual uses the smudge filter for the date expansion, but in my case it must be clean. I want the date substituted with the current timestamp during the commit.

    This must be done in the directory where the git repository is.

    Filters from Example:

    $ git config filter.dater.smudge expand_date
    $ git config filter.dater.clean 'perl -pe "s/\\\$Date[^\\\$]*\\\$/\\\$Date\\\$/"'
    

    Check with gitconfig -l if the settings are applied.

    Setup Git Attributes

    Create in the respective git repository the .gitattributes file. To apply the filter to all jekyll files, add the file extension for markdown and assign the filter, which was previously configured.

    tan@omega:~/Sources/cinhtau.github.io$ cat .gitattributes 
    *.md filter=dater
    

    The basic problem is that filters only work on checkout and add. Following the example I always had to remove and make a checkout the file to get the date substitution. This is a very extensive effort.

    To modify a file on commit mostly the pre-commit hook is the right way to accomplish this.

    Pre-Commit Hook

    Git has examples files in the .git/hooks directory. Based on that I wrote this simple pre-commit script. It must be named pre-commit and must be placed in the hooks directory.

    #!/bin/bash
    
    if git rev-parse --verify HEAD >/dev/null 2>&1 ; then
       against=HEAD
    else
       # Initial commit: diff against an empty tree object
       against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
    fi
    
    staged_files=`git diff-index --name-status --cached $against      | # Find all staged files
                    egrep -i '^(A|M).*\.(md)$' 		                  | # Only process jekyll files
                    sed -e 's/^[AM][[:space:]]*//'                    | # Remove leading git info
                    sort                                              | # Remove duplicates
                    uniq`
    
    
    partially_staged_files=`git status --porcelain --untracked-files=no | # Find all staged files
                            egrep -i '^(A|M)M '                         | # Filter only partially staged files
                            sed -e 's/^[AM]M[[:space:]]*//'             | # Remove leading git info
                            sort                                        | # Remove duplicates
                            uniq`
    
    # Merge staged files and partially staged files
    staged_and_partially_staged_files=${staged_files}$'\n'${partially_staged_files}
    
    # Remove all files that are staged *AND* partially staged
    # Thus we get only the fully staged files
    fully_staged_files=`echo "$staged_and_partially_staged_files" | sort | uniq -u`
    
    for FILE in $fully_staged_files ; do
        # substitute every jekyll modified timestamp with current timestamp
        sed -i "1,10s/modified:.*/modified: \'$(date +'%Y-%m-%d %H:%M:%S %z')\'/" "$FILE"
    done
    

    Pay attention, to replace only the modified in the frontmatter, sed is limited to lines 1 to 10. Ensure that modified is listed in this range.

    sed -i "1,10s/modified:.*/modified: \'$(date +'%Y-%m-%d %H:%M:%S %z')\'/" "$FILE"
    

    Testing

    Now let’s do some testing. Show modified files.

    tan@omega:~/sources/cinhtau.github.io$ git status
    On branch master
    Your branch is up-to-date with 'origin/master'.
    Changes to be committed:
      (use "git reset HEAD <file>..." to unstage)
    
            renamed:    scripts/prepare-commit-jekyll -> scripts/pre-commit-jekyll
    
    Changes not staged for commit:
      (use "git add <file>..." to update what will be committed)
      (use "git checkout -- <file>..." to discard changes in working directory)
    
            modified:   .gitattributes
            modified:   Gemfile        
            modified:   _posts/2017/07/2017-07-17-update-jekyll-meta-data.md
    

    Commit the jekyll post

    tan@omega:~/sources/cinhtau.github.io$ git commit _posts/2017/07/2017-07-17-update-jekyll-meta-data.md -m "test pre-commit"
    [master cefec94] test pre-commit
     1 file changed, 11 insertions(+), 7 deletions(-)
    

    Check the date substitution. :raised_hands:

    tan@omega:~/sources/cinhtau.github.io$ head _posts/2017/07/2017-07-17-update-jekyll-meta-data.md
    ---
    layout: post
    published: true
    title: Update Jekyll blog entry meta-data
    author: cinhtau
    date: '24.07.2017 07:49'
    modified: '2017-07-25 10:36:08 +0200'
    categories:
    - IT
    tags:
    
  2. 2017-04-24 - Rename multiple files; Tags: Rename multiple files
    Loading...

    Rename multiple files

    My current migration from WordPress to Jekyll took me the WordPress exporter of Jekyll. It generated html files. I want to migrate them to markdown, therefore I needed a quick solution to rename all html files into files with markdown file extensions.

    Let’s have a look first on directory structure:

    tan@omega:~/sources/my-awesome-site/_posts$ ll
    total 28
    drwxrwx--- 1 tan tan     0 Apr 23 21:10 ./
    drwxrwx--- 1 tan tan 24576 Apr 24 09:29 ../
    drwxrwx--- 1 tan tan     0 Apr 23 21:10 2015/
    drwxrwx--- 1 tan tan  4096 Apr 23 21:10 2016/
    drwxrwx--- 1 tan tan     0 Apr 23 21:10 2017/
    

    Let’s check the last 10 entries

    tan@omega:~/sources/my-awesome-site/_posts$ find . -name "*.html" -exec echo {} \; | tail
    ./2016/09/2016-09-14-localization-problem-while-deinstalling-oracle-11g-on-windows.html
    ./2016/09/2016-09-15-handling-logstash-input-multiline-codec.html
    ./2016/09/2016-09-19-reindex-data-in-elasticsearch.html
    ./2016/09/2016-09-20-amazing-video-for-an-amazing-song.html
    ./2016/09/2016-09-21-groups-of-groups-in-ansible.html
    ./2016/09/2016-09-21-secret-nations-tonight.html
    ./2016/09/2016-09-24-use-ansible-for-cluster-management.html
    ./2016/09/2016-09-25-correct-type-mapping-in-index-template-for-elasticsearch.html
    ./2016/09/2016-09-28-checking-for-running-port-on-windows-cmd.html
    ./2016/09/2016-09-28-monitor-process-and-used-ports-of-kibana.html
    

    Total sum of affected files

    tan@omega:~/sources/my-awesome-site/_posts$ find . -name "*.html" -exec echo {} \; | wc -l
    280
    

    Use Perl’s rename command with regular expression:

    find . -name "*.html" -exec rename -v 's/\.html$/\.md/' {} \;
    

    The verbose option of rename shows the detailed rename action.

    ./2016/09/2016-09-15-handling-logstash-input-multiline-codec.html renamed as ./2016/09/2016-09-15-handling-logstash-input-multiline-codec.md
    ./2016/09/2016-09-19-reindex-data-in-elasticsearch.html renamed as ./2016/09/2016-09-19-reindex-data-in-elasticsearch.md
    ./2016/09/2016-09-20-amazing-video-for-an-amazing-song.html renamed as ./2016/09/2016-09-20-amazing-video-for-an-amazing-song.md
    ./2016/09/2016-09-21-groups-of-groups-in-ansible.html renamed as ./2016/09/2016-09-21-groups-of-groups-in-ansible.md
    ./2016/09/2016-09-21-secret-nations-tonight.html renamed as ./2016/09/2016-09-21-secret-nations-tonight.md
    ./2016/09/2016-09-24-use-ansible-for-cluster-management.html renamed as ./2016/09/2016-09-24-use-ansible-for-cluster-management.md
    ./2016/09/2016-09-25-correct-type-mapping-in-index-template-for-elasticsearch.html renamed as ./2016/09/2016-09-25-correct-type-mapping-in-index-template-for-elasticsearch.md
    ./2016/09/2016-09-28-checking-for-running-port-on-windows-cmd.html renamed as ./2016/09/2016-09-28-checking-for-running-port-on-windows-cmd.md
    ./2016/09/2016-09-28-monitor-process-and-used-ports-of-kibana.html renamed as ./2016/09/2016-09-28-monitor-process-and-used-ports-of-kibana.md
    
  3. 2017-04-24 - Create file templates for Jekyll posts; Tags: Create file templates for Jekyll posts
    Loading...

    Create file templates for Jekyll posts

    Writing Jekyll posts always require a YAML front matter block content. To speed up the task you may create a file template for IntelliJ or Webstorm, depending which IDE from Jetbrains you are using. The procedure is equal.

    First create a new file template.

    Create new file template

    In this template you can use the internal variables provided by the IDEA platform. The author and date using variables as default values. The title is requested.

    This is my template content. Adjust it to your needs.

    ---
    layout: post
    status: publish
    published: true
    title: $title
    author: ${USER}
    date: '${DATE} ${TIME}'
    categories: []
    tags: []
    comments: []
    ---
    

    Pay attention in which scope (default and project)the template exists.

    Jekyll Post template

    After that you just create a new file and input the requested information.

    Create new Jekyll post