Skip to content

Commit

Permalink
Fixed a ton of bugs, added menu bar widget, tweaked icon.
Browse files Browse the repository at this point in the history
  • Loading branch information
borismus committed Sep 13, 2013
1 parent c90768d commit ed3a138
Show file tree
Hide file tree
Showing 14 changed files with 494 additions and 236 deletions.
142 changes: 107 additions & 35 deletions lightning
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import yaml
import markdown2
import sys

import boto
from boto.s3.key import Key


PREVIEW_ADDR = '127.0.0.1'
PREVIEW_PORT = 8000

Expand Down Expand Up @@ -64,6 +68,7 @@ class SiteBuilder:

return files


def get_cache(self):
"""Gets all of the files involved in the previously built version of the
static site.
Expand Down Expand Up @@ -204,21 +209,21 @@ class SiteBuilder:
data['is_long'] = bool(snip)
data['snip'] = snip or content
# Put everything in a dict.
data['title'] = title
data['title'] = unicode(title, 'utf8')
data['content'] = content
# Infer slug and type from path.
slug = 'slug' in data and data['slug'] or self.parse_slug(path)
type_name = 'type' in data and data['type'] or self.parse_type(path)
data['slug'] = slug
data['type'] = type_name
data['summary'] = markdown_body[:markdown_body.find('.')+1]
summary = markdown_body[:markdown_body.find('.')+1]
data['summary'] = summary
description = 'description' in data and markdown2.markdown(data['description']) \
or None
data['description'] = description
# Parse the date if it's specified.
posted_info = None
if 'posted' in data:
print title
posted_info = self.parse_date(data['posted'])
data['posted_info'] = posted_info
# Compute the permalink.
Expand Down Expand Up @@ -349,6 +354,8 @@ class SiteBuilder:
# TODO: validate the item!
# Combine the parsed information into template data.
template_data = dict(info.items() + self.site_info.items())
# Compute the final path based on permalink config.
path = info['permalink']
# If it's a list, also get the list parameters.
if 'list' in info:
limit = 'limit' in info and info['limit'] or 10
Expand All @@ -364,8 +371,6 @@ class SiteBuilder:
template_path = type_name + '.html'
# Evaluate the template with data.
html = self.render_template(template_path, template_data)
# Compute the final path based on permalink config.
path = info['permalink']
# Create the directory for the parsed HTML.
abs_path = self.output_root + path
dir_util.mkpath(abs_path)
Expand Down Expand Up @@ -521,7 +526,7 @@ class SiteBuilder:

# If nothing changed, we're done.
if not created and not updated and not deleted:
print 'Nothing to do.'
print 'Incremental build: nothing to do.'
return
else:
print 'Created %d, updated %d, deleted %d.' % \
Expand Down Expand Up @@ -576,13 +581,36 @@ class SiteBuilder:
# Write out the new cache to disk.
self.save_cache(cache)

def get_list_pathes(self):
out = []
cache = self.get_cache()
lists = [i for i in cache if 'list' in i['info']]
for item in lists:
item_info = item['info']
if 'permalink' in item_info:
item_type = item_info['type']
permalink = item_info['permalink']
# Ignore image_index pages.
if item_type == 'image_index':
continue
path = permalink
if item_type == 'feed':
path = permalink + '.xml'
elif item_type == 'index':
path = permalink + 'index.html'
elif item_type == 'archive':
path = os.path.join(permalink, 'index.html')
out.append(path)
return out

class Command:
BUILD = 1 # Incremental build.
REBUILD = 2
PREVIEW = 3
WATCH = 4
PURGE = 5
DEPLOY = 6
DEPLOY_PERMALINK = 7

command_map = {
'build': Command.BUILD,
Expand All @@ -591,6 +619,7 @@ command_map = {
'watch': Command.WATCH,
'purge': Command.PURGE,
'deploy': Command.DEPLOY,
'deploy_permalink': Command.DEPLOY_PERMALINK,
}

def error(msg):
Expand All @@ -612,42 +641,65 @@ class BuildHandler(FileSystemEventHandler):

class S3Uploader:

def upload(self, local_directory, s3_bucket):
import boto
from boto.s3.key import Key
def __init__(self, local_directory, s3_bucket):
self.local_directory = local_directory
self.s3_bucket = s3_bucket

def upload(self, pathes=None):
keys = []
# Get the list of files to upload.
if pathes:
for path in pathes:
# Build up the key to upload based on this permalink.
key = path.strip('/')
keys.append(key)
else:
# Upload directory recursively.
for path, dir, files in os.walk(self.local_directory):
for filename in files:
filepath = os.path.join(path, filename)
key = os.path.relpath(os.path.join(path, filename), self.local_directory)
keys.append(key)

self.upload_keys(keys)

def upload_keys(self, keys):
# Establish connection.
c = boto.connect_s3()

# Get or create bucket with proper permissions.
try:
b = c.get_bucket(s3_bucket)
b = c.get_bucket(self.s3_bucket)
except Exception:
b = c.create_bucket(s3_bucket)
print 'No bucket %s found.' % self.s3_bucket
b = c.create_bucket(self.s3_bucket)
k = Key(b)

# Upload directory recursively.
for path, dir, files in os.walk(local_directory):
for filename in files:
filepath = os.path.join(path, filename)
key = os.path.relpath(os.path.join(path, filename), local_directory)
# Check if a file with this key already exists.
remote_key = b.get_key(key)
if remote_key:
# If it does, check if the files are identical.
# Note: S3 stores uses MD5 for their ETags. http://goo.gl/rGVXM
local_md5 = k.compute_md5(open(filepath))[0]
remote_md5 = remote_key.etag.strip('"')
if local_md5 == remote_md5:
print '%s is already uploaded. Skipping.' % key
# If the files are identical, do nothing.
continue;

# Otherwise if no file exists, or if they are different, upload.
k.key = key
k.set_contents_from_filename(filepath)
b.set_acl('public-read', k.key)
print 'Uploading %s.' % k.key
for key in keys:
filepath = os.path.join(self.local_directory, key.strip('/'))
print filepath
# Check if a file with this key already exists.
remote_key = b.get_key(key)
if remote_key:
# If it does, check if the files are identical.
# Note: S3 stores uses MD5 for their ETags. http://goo.gl/rGVXM
local_md5 = k.compute_md5(open(filepath))[0]
remote_md5 = remote_key.etag.strip('"')
if local_md5 == remote_md5:
print '%s is already uploaded. Skipping.' % key
# If the files are identical, do nothing.
continue;

# Otherwise if no file exists, or if they are different, upload.
k.key = key
k.set_contents_from_filename(filepath)
b.set_acl('public-read', k.key)
print 'Uploading %s.' % k.key

def verify_path(self, permalink):
path = os.path.join(self.local_directory, permalink.strip('/'))
return os.path.exists(path)



if __name__ == '__main__':
Expand Down Expand Up @@ -703,6 +755,26 @@ if __name__ == '__main__':
builder.build_incremental()
print 'Deploying to %s.' % builder.deploy
# Create an S3 uploader.
uploader = S3Uploader()
uploader = S3Uploader(builder.output_root, builder.deploy)
# Upload.
uploader.upload(builder.output_root, builder.deploy)
uploader.upload()

elif command is Command.DEPLOY_PERMALINK:
# First, parse out the permalink to deploy.
permalink = os.path.join(sys.argv[2], 'index.html')
if len(sys.argv) != 3:
error('deploy_permalink requires you to specify exactly one permalink path.')
uploader = S3Uploader(builder.output_root, builder.deploy)
# Verify that the permalink points to a file that exists.
if not uploader.verify_path(permalink):
error('No file found at specified permalink: %s.' % permalink)
# Build incrementally to make sure we're up to date.
builder.build_incremental()
# Put the permalink into the list of pathes to update.
pathes = [permalink]
# Get all of the index files that may have also updated.
pathes += builder.get_list_pathes()
# Tell the uploader to do a selective upload (just the permalink that was
# specified and all of the indexes).
print 'Doing partial deploy of just %s and index pages to S3.' % permalink
uploader.upload(pathes)
8 changes: 8 additions & 0 deletions link/Lightning.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
objects = {

/* Begin PBXBuildFile section */
CA37DED017DB889400E643DA /* status-hi.png in Resources */ = {isa = PBXBuildFile; fileRef = CA37DECE17DB889400E643DA /* status-hi.png */; };
CA37DED117DB889400E643DA /* status.png in Resources */ = {isa = PBXBuildFile; fileRef = CA37DECF17DB889400E643DA /* status.png */; };
CA76C4C117911F0E00CF5775 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CA76C4C017911F0E00CF5775 /* Cocoa.framework */; };
CA76C4C317911F0E00CF5775 /* Python.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CA76C4C217911F0E00CF5775 /* Python.framework */; };
CA76C4CD17911F0E00CF5775 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = CA76C4CB17911F0E00CF5775 /* InfoPlist.strings */; };
Expand All @@ -23,6 +25,8 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
CA37DECE17DB889400E643DA /* status-hi.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "status-hi.png"; sourceTree = "<group>"; };
CA37DECF17DB889400E643DA /* status.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = status.png; sourceTree = "<group>"; };
CA76C4BD17911F0E00CF5775 /* Lightning.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Lightning.app; sourceTree = BUILT_PRODUCTS_DIR; };
CA76C4C017911F0E00CF5775 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
CA76C4C217911F0E00CF5775 /* Python.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Python.framework; path = System/Library/Frameworks/Python.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -114,6 +118,8 @@
CAAEE74517A23FCE00CEF86E /* Lightning.iconset */,
CA76C4CA17911F0E00CF5775 /* Lightning-Info.plist */,
CA76C4CB17911F0E00CF5775 /* InfoPlist.strings */,
CA37DECE17DB889400E643DA /* status-hi.png */,
CA37DECF17DB889400E643DA /* status.png */,
CA76C4CE17911F0E00CF5775 /* main.m */,
CA76C4D017911F0E00CF5775 /* Lightning-Prefix.pch */,
CA76C4D117911F0E00CF5775 /* Credits.rtf */,
Expand Down Expand Up @@ -183,6 +189,8 @@
CA76C4EE179387FC00CF5775 /* Syndicator.py in Resources */,
CAAEE74417A23D9800CEF86E /* open-chrome-tab.scpt in Resources */,
CAAEE74617A23FCE00CEF86E /* Lightning.iconset in Resources */,
CA37DED017DB889400E643DA /* status-hi.png in Resources */,
CA37DED117DB889400E643DA /* status.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
Binary file not shown.
9 changes: 6 additions & 3 deletions link/Lightning/AppDelegate.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@

#from Foundation import *
from Foundation import NSObject, NSLog
from Cocoa import NSWindowController


class AppDelegate(NSObject):
def applicationDidFinishLaunching_(self, sender):
NSLog("Application did finish launching.")

def applicationWillTerminate_(self,sender):
NSLog("Application will terminate.")

def applicationShouldTerminateAfterLastWindowClosed_(self, sender):
return True
return False

def applicationDidFinishLaunching_(self, sender):
NSLog("Application did finish launching.")
2 changes: 2 additions & 0 deletions link/Lightning/Lightning-Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,7 @@
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>LSUIElement</key>
<string>1</string>
</dict>
</plist>
Binary file modified link/Lightning/Lightning.icns
Binary file not shown.
Binary file modified link/Lightning/Lightning.iconset/icon_128x128.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit ed3a138

Please sign in to comment.