Merge remote-tracking branch 'upstream/master' into tests
This commit is contained in:
commit
08543af540
21
.travis.yml
21
.travis.yml
@ -4,5 +4,24 @@ python:
|
|||||||
- "3.4"
|
- "3.4"
|
||||||
- "3.5"
|
- "3.5"
|
||||||
install: "pip install -r requirements.txt"
|
install: "pip install -r requirements.txt"
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- debhelper
|
||||||
|
- devscripts
|
||||||
|
- zsh
|
||||||
script:
|
script:
|
||||||
- ./tests/run_tests.sh
|
- ./tests/ci-test-wrapper --watch .travis.yml
|
||||||
|
- git fetch --unshallow --tags origin
|
||||||
|
- ./tools/makedeb
|
||||||
|
deploy:
|
||||||
|
provider: releases
|
||||||
|
api-key:
|
||||||
|
secure: Zf+3StERDV9B0knxNj9UdiMv9kmrE9d80a27/e7IioZv6CUvCqbIpgzN5bD3yoTlJsHq3hY6BHF8OQpkH0B0pj3xwcxgcicwDdpGA9o43aIA+zqNSb6w1VHm784KZ+Z+z1NcVNEzCyIONXEIV0KRe73NUU/7Re6heA46lPDIMFF0EL8Fjv5tPb5VLq3z0jvA8mNlXfqiwtiWT/Zz7y6PvbKQZ5nSebK0WVBdGhuaQLj9EKNwdnxkgH3gsA1gAtiuaQdgDUxF69Xf5VY6hZPhdK5LSLl/5HDpandX9nLu5j3ZuSHn1pJWgdKw72aeWYSpKtgnBQ/uS5JLamqK31kHXfRVebp0uB2I1RBiLYhb5T0MO8BnFc6O+/f2qS7nQHGKZ9M+Mo+I+ceharLmCt7KfDA1yBP+AnwjsHYe1zgnGZfwSm+/ny1R1NoVmuyXPHkEDviOsT5JLSfLvuzCUstY4gsAYyXKHLDbHfMLxXQRRfK1RoJzR4taMntmsWsl2fIshzKujeck1o4wRu/FQIlq2ANYQVNrrcDSO+C5lZkSA8iivg7lIXk/n9Lxk7QcJkvrZkzOg0y9EKAejY87vejpessG1t2OD7GwUqWZMBBlPJXnbfTiUzTJqC+b8brwnAhu/QI8jMUvxWkTMO7XOiyZBpQljv2U9MwFNH8Ge4fwIag=
|
||||||
|
file_glob: true
|
||||||
|
file: dist/*.deb
|
||||||
|
on:
|
||||||
|
repo: jarun/Buku
|
||||||
|
tags: true
|
||||||
|
# Upload from only one job (doesn't matter which one because we're packaging the same thing throughout the matrix)
|
||||||
|
python: "3.5"
|
||||||
|
167
CHANGELOG
Normal file
167
CHANGELOG
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Buku v2.1
|
||||||
|
2016-05-28
|
||||||
|
|
||||||
|
Modifications
|
||||||
|
- Import bookmarks from Firefox, Google Chrome or IE html bookmark exports
|
||||||
|
- Support comments on bookmarks
|
||||||
|
- Prettier output using symbols (`>` title, `+` comments, `#` tags)
|
||||||
|
- New option (`--st`, `--stag`) to search by tag
|
||||||
|
- New option (`--noprompt`) for noninteractive mode
|
||||||
|
- New options (`--url` and `--tag`)
|
||||||
|
- `--update` now handles each option (url, tag, title, comment) independently
|
||||||
|
- Several messages removed or moved to debug
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Buku v2.0
|
||||||
|
2016-05-15
|
||||||
|
|
||||||
|
Modifications
|
||||||
|
To begin with, 2.0 is a significant release with respect to options. `Buku` now has fewer options with more (and merged) functionality. Please go through the program help at least once to understand the changes.
|
||||||
|
|
||||||
|
- Replace getopt with argparse for parsing arguments
|
||||||
|
- Long options for each short option
|
||||||
|
- Options changed
|
||||||
|
- insert: removed as automatic DB compaction serves the purpose (previously `-i`)
|
||||||
|
- iterations: removed as optional argument to `-l` and `-k` (previously `-t`)
|
||||||
|
- title: `-t` is now the short option to set title manually (previously `-m`)
|
||||||
|
- Special search keywords for ALL search (`-S`):
|
||||||
|
- tags: show all tags (previously `-g`)
|
||||||
|
- blank: show bookmarks with empty tags (previously `-e`)
|
||||||
|
- lock/unlock: now accepts number of hash iterations to generate key
|
||||||
|
- format: print formatting option changed to `-f` (previously `-x`)
|
||||||
|
- help: option added to show program help
|
||||||
|
- Following options apply to ALL bookmarks without arguments
|
||||||
|
- `-u`, `--update`
|
||||||
|
- `-d`, `--delete`
|
||||||
|
- `-p`, `--print`
|
||||||
|
- Shell-completion scripts for Bash, Fish and Zsh
|
||||||
|
- Warn if URL is not HTTP(S)
|
||||||
|
- More comprehensive help
|
||||||
|
- Fix a bug with deletion when only one entry in DB
|
||||||
|
- Some import dependencies removed or late loaded (if optional)
|
||||||
|
- Handle exception if DB file is encrypted or invalid
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Buku 1.9
|
||||||
|
2016-04-23
|
||||||
|
|
||||||
|
Modifications
|
||||||
|
- **New location for database file** (refer to README or man page). The old database file, if exists, is migrated automatically.
|
||||||
|
- **Removed options**
|
||||||
|
- `-P`: (print all) is now `-p 0`
|
||||||
|
- `-D`: (delete all) is now `-d 0`
|
||||||
|
- `-R`: (update all) is now `-u 0`
|
||||||
|
- `-w`: title web fetch is now the default behaviour, override with `-m title` option
|
||||||
|
- **Change in search behaviour**
|
||||||
|
- `-s`: search bookmarks for ANY keyword in URL, title or tags
|
||||||
|
- `-S`: search bookmarks for ALL keywords in URL, title or tags
|
||||||
|
- Update only title of a bookmark (`-u N`)
|
||||||
|
- Set empty title (`-m none`)
|
||||||
|
- Support HTTP(S) gzip compression
|
||||||
|
- Optional JSON output for `-p` and `-s` options (thanks @CaptainQuirk)
|
||||||
|
- Reformatted help and man page with general options on top
|
||||||
|
- Optimize add and insert: ensure URL is not in DB already
|
||||||
|
- Handle URLs passed with %xx escape
|
||||||
|
- Retry with truncated resource path on HTTP error 500
|
||||||
|
- Several code optimizations
|
||||||
|
- Catchier errors and warnings
|
||||||
|
- Version added to debug logs
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Buku 1.8
|
||||||
|
2016-03-26
|
||||||
|
|
||||||
|
Modifications
|
||||||
|
- Auto compact DB on single record removal
|
||||||
|
- Handle piped input
|
||||||
|
- Better tag management
|
||||||
|
- Tag modify or delete support
|
||||||
|
- Show unique tags alphabetically
|
||||||
|
- Full DB refresh
|
||||||
|
- Fix stuff broken earlier
|
||||||
|
- Optimize to update titles only
|
||||||
|
- Update titles only if non-empty to preserve earlier data
|
||||||
|
- Redirection
|
||||||
|
- Handle multiple redirections
|
||||||
|
- Detect redirection loop and break
|
||||||
|
- Show redirected link in bold
|
||||||
|
- List all bookmarks with no title or tags (for manual bookkeeping)
|
||||||
|
- Confirm full DB removal
|
||||||
|
- Better comma (`,`) separator handling for tags
|
||||||
|
- Help
|
||||||
|
- Place regular options before power options in program help
|
||||||
|
- Help added in man page for quick reference
|
||||||
|
- Additional examples for new features
|
||||||
|
- Errors & warnings
|
||||||
|
- Error out if both encrypted and flat DB files exist
|
||||||
|
- Catchier error and warning messages
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Buku 1.7
|
||||||
|
2016-03-15
|
||||||
|
|
||||||
|
Modifications
|
||||||
|
- Add title manually using option `-m`
|
||||||
|
- Unquote redirected URL
|
||||||
|
- Quit on `Ctrl-d` at prompt
|
||||||
|
- More dynamic shebang for python3
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Buku 1.6
|
||||||
|
2016-01-22
|
||||||
|
|
||||||
|
Modifications
|
||||||
|
- Stronger encryption: 256-bit salt, multi-hash key.
|
||||||
|
- Allow user to specify number of iterations to generate key (check option `-t`).
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Buku 1.5
|
||||||
|
2015-12-20
|
||||||
|
|
||||||
|
Modifications
|
||||||
|
- Project name changed to `Buku` to avoid any copyright issues. This also means old users have to move the database file. Run:
|
||||||
|
<pre>$ mkdir ~/.cache/buku/
|
||||||
|
$ mv ~/.cache/markit/bookmarks.db ~/.cache/buku/bookmarks.db
|
||||||
|
$ rm -rf ~/.cache/markit/bookmarks.db</pre>
|
||||||
|
- Manual AES256 encryption and decryption support (password protection) implemented. This adds dependency on PyCrypto module. Installation instructions updated in README.
|
||||||
|
- Some typos fixed (thanks @GuilhermeHideki)
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
MarkIt v1.4
|
||||||
|
2015-11-13
|
||||||
|
|
||||||
|
Modifications
|
||||||
|
- Refresh full bookmark database. Fetch titles from the web, retain tags.
|
||||||
|
- Notify empty titles in red during online add or update.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
MarkIt v1.2
|
||||||
|
2015-11-11
|
||||||
|
|
||||||
|
Modifications
|
||||||
|
- Introduced `-S` search option to match ALL keywords in URL or title
|
||||||
|
- Introduced `-x` option to show unformatted selective output (for creating batch scripts)
|
||||||
|
- Added examples on batch add and update (refresh) scripts
|
||||||
|
- Handle multiple title tags in page
|
||||||
|
- Handle title data within another tag (e.g. head)
|
||||||
|
- Show DB index in search results, removal and update confirmation message
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
MarkIt v1.1
|
||||||
|
2015-11-10
|
||||||
|
|
||||||
|
Modifications
|
||||||
|
- Replace Unicode chars in title data before UTF-8 decoding (for parser to succeed).
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
@ -199,7 +199,7 @@ Shell completion scripts for Bash, Fish and Zsh can be found in respective subdi
|
|||||||
- -S : match all the keywords in URL, title or tags.
|
- -S : match all the keywords in URL, title or tags.
|
||||||
- --st : search bookmarks by tag, or show all tags alphabetically.
|
- --st : search bookmarks by tag, or show all tags alphabetically.
|
||||||
- You can search bookmarks by tag (see [examples](#examples)).
|
- You can search bookmarks by tag (see [examples](#examples)).
|
||||||
- Search results are indexed serially. This index is different from actual database index of a bookmark record which is shown within `[]` after the URL.
|
- Search results are indexed serially. This index is different from actual database index of a bookmark record which is shown in bold within `[]` after the URL.
|
||||||
- Auto DB compaction: when a record is deleted, the last record is moved to the index.
|
- Auto DB compaction: when a record is deleted, the last record is moved to the index.
|
||||||
- **Encryption** is optional and manual. AES256 algorithm is used. If you choose to use encryption, the database file should be unlocked (-k) before using buku and locked (-l) afterwards. Between these 2 operations, the database file lies unencrypted on the disk, and NOT in memory. Also, note that the database file is *unencrypted on creation*.
|
- **Encryption** is optional and manual. AES256 algorithm is used. If you choose to use encryption, the database file should be unlocked (-k) before using buku and locked (-l) afterwards. Between these 2 operations, the database file lies unencrypted on the disk, and NOT in memory. Also, note that the database file is *unencrypted on creation*.
|
||||||
|
|
||||||
|
84
buku
84
buku
@ -438,6 +438,8 @@ class BukuDb:
|
|||||||
|
|
||||||
def update_bookmark(self, index, url='', title_manual=None, tag_manual=None, desc=None):
|
def update_bookmark(self, index, url='', title_manual=None, tag_manual=None, desc=None):
|
||||||
""" Update an existing record at index
|
""" Update an existing record at index
|
||||||
|
Update all records if index is 0 and url is not specified.
|
||||||
|
URL is an exception because URLs are unique in DB.
|
||||||
|
|
||||||
:param index: int position to update
|
:param index: int position to update
|
||||||
:param url: address
|
:param url: address
|
||||||
@ -487,7 +489,9 @@ class BukuDb:
|
|||||||
print('Title: [%s]' % meta)
|
print('Title: [%s]' % meta)
|
||||||
elif not to_update:
|
elif not to_update:
|
||||||
self.refreshdb(index)
|
self.refreshdb(index)
|
||||||
self.print_bookmark(index)
|
if index > 0:
|
||||||
|
self.print_bookmark(index)
|
||||||
|
return
|
||||||
|
|
||||||
if meta is not None:
|
if meta is not None:
|
||||||
query = '%s metadata = ?,' % query
|
query = '%s metadata = ?,' % query
|
||||||
@ -497,8 +501,20 @@ class BukuDb:
|
|||||||
if not to_update: # Nothing to update
|
if not to_update: # Nothing to update
|
||||||
return
|
return
|
||||||
|
|
||||||
query = '%s WHERE id = ?' % query[:-1]
|
if index == 0: # Update all records
|
||||||
arguments += (index,)
|
if url != '':
|
||||||
|
printmsg('All URLs cannot be same', 'ERROR')
|
||||||
|
return
|
||||||
|
|
||||||
|
resp = input('ALL bookmarks will be updated. Enter \x1b[1my\x1b[21m to confirm: ')
|
||||||
|
if resp != 'y':
|
||||||
|
return
|
||||||
|
|
||||||
|
query = query[:-1]
|
||||||
|
else:
|
||||||
|
query = '%s WHERE id = ?' % query[:-1]
|
||||||
|
arguments += (index,)
|
||||||
|
|
||||||
if debug:
|
if debug:
|
||||||
print('query: [%s], args: [%s]' % (query, arguments))
|
print('query: [%s], args: [%s]' % (query, arguments))
|
||||||
|
|
||||||
@ -507,19 +523,18 @@ class BukuDb:
|
|||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
if self.cur.rowcount == 1:
|
if self.cur.rowcount == 1:
|
||||||
self.print_bookmark(index)
|
self.print_bookmark(index)
|
||||||
else:
|
elif self.cur.rowcount == 0:
|
||||||
print('No matching index')
|
print('No matching index')
|
||||||
except sqlite3.IntegrityError:
|
except sqlite3.IntegrityError:
|
||||||
print('URL already exists')
|
print('URL already exists')
|
||||||
|
|
||||||
def refreshdb(self, index, title_manual=None):
|
def refreshdb(self, index):
|
||||||
"""Refresh ALL records in the database. Fetch title for each
|
"""Refresh ALL records in the database. Fetch title for each
|
||||||
bookmark from the web and update the records. Doesn't udpate
|
bookmark from the web and update the records. Doesn't udpate
|
||||||
the record if title is empty.
|
the record if title is empty.
|
||||||
This API doesn't change DB index, URL or tags of a bookmark.
|
This API doesn't change DB index, URL or tags of a bookmark.
|
||||||
|
|
||||||
:param index: index of record to update, or 0 for all records
|
:param index: index of record to update, or 0 for all records
|
||||||
:param title_manual: custom title
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if index == 0:
|
if index == 0:
|
||||||
@ -528,26 +543,19 @@ class BukuDb:
|
|||||||
self.cur.execute('SELECT id, url FROM bookmarks WHERE id = ?', (index,))
|
self.cur.execute('SELECT id, url FROM bookmarks WHERE id = ?', (index,))
|
||||||
|
|
||||||
resultset = self.cur.fetchall()
|
resultset = self.cur.fetchall()
|
||||||
if title_manual is None:
|
for row in resultset:
|
||||||
for row in resultset:
|
title = network_handler(row[1])
|
||||||
title = network_handler(row[1])
|
if title == '':
|
||||||
if title == '':
|
print('\x1b[1mIndex %d: empty title\x1b[21m\x1B[0m\n' % row[0])
|
||||||
print('\x1b[1mIndex %d: empty title\x1b[21m\x1B[0m\n' % row[0])
|
continue
|
||||||
continue
|
else:
|
||||||
else:
|
print('Title: [%s]' % title)
|
||||||
print('Title: [%s]' % title)
|
|
||||||
|
|
||||||
self.cur.execute('UPDATE bookmarks SET metadata = ? WHERE id = ?', (title, row[0],))
|
self.cur.execute('UPDATE bookmarks SET metadata = ? WHERE id = ?', (title, row[0],))
|
||||||
print('Index %d updated\n' % row[0])
|
print('Index %d updated\n' % row[0])
|
||||||
if interrupted:
|
if interrupted:
|
||||||
printmsg('Aborting refreshdb ...', 'WARNING')
|
printmsg('Aborting refreshdb ...', 'WARNING')
|
||||||
break
|
break
|
||||||
else:
|
|
||||||
title = title_manual
|
|
||||||
|
|
||||||
for row in resultset:
|
|
||||||
self.cur.execute('UPDATE bookmarks SET metadata = ? WHERE id = ?', (title, row[0],))
|
|
||||||
print('Index %d updated\n' % row[0])
|
|
||||||
|
|
||||||
self.conn.commit()
|
self.conn.commit()
|
||||||
|
|
||||||
@ -728,7 +736,7 @@ class BukuDb:
|
|||||||
|
|
||||||
def replace_tag(self, orig, new=None):
|
def replace_tag(self, orig, new=None):
|
||||||
"""Replace orig tags with new tags in DB for all records.
|
"""Replace orig tags with new tags in DB for all records.
|
||||||
Remove orig tag is new tag is empty.
|
Remove orig tag if new tag is empty.
|
||||||
|
|
||||||
Params: original and new tags
|
Params: original and new tags
|
||||||
"""
|
"""
|
||||||
@ -759,6 +767,7 @@ class BukuDb:
|
|||||||
newtags = DELIMITER
|
newtags = DELIMITER
|
||||||
|
|
||||||
tags = row[1].replace(orig, newtags)
|
tags = row[1].replace(orig, newtags)
|
||||||
|
tags = parse_tags([tags])
|
||||||
self.cur.execute('UPDATE bookmarks SET tags = ? WHERE id = ?', (tags, row[0],))
|
self.cur.execute('UPDATE bookmarks SET tags = ? WHERE id = ?', (tags, row[0],))
|
||||||
print('Index %d updated' % row[0])
|
print('Index %d updated' % row[0])
|
||||||
update = True
|
update = True
|
||||||
@ -1183,7 +1192,7 @@ def print_record(row, count=0):
|
|||||||
|
|
||||||
# Print index and URL
|
# Print index and URL
|
||||||
if count != 0:
|
if count != 0:
|
||||||
printstr = '\x1B[1m\x1B[93m%d. \x1B[0m\x1B[92m%s\x1B[0m\t[%d]\n' % (count, row[1], row[0])
|
printstr = '\x1B[1m\x1B[93m%d. \x1B[0m\x1B[92m%s\x1B[0m \x1B[1m[%s]\x1B[0m\n' % (count, row[1], row[0])
|
||||||
else:
|
else:
|
||||||
printstr = '\x1B[1m\x1B[93m%d. \x1B[0m\x1B[92m%s\x1B[0m\n' % (row[0], row[1])
|
printstr = '\x1B[1m\x1B[93m%d. \x1B[0m\x1B[92m%s\x1B[0m\n' % (row[0], row[1])
|
||||||
|
|
||||||
@ -1565,21 +1574,22 @@ if __name__ == '__main__':
|
|||||||
# Update record
|
# Update record
|
||||||
if update:
|
if update:
|
||||||
if len(args.update) == 0:
|
if len(args.update) == 0:
|
||||||
bdb.refreshdb(0, titleManual)
|
update_index = 0
|
||||||
elif not args.update[0].isdigit():
|
elif not args.update[0].isdigit():
|
||||||
printmsg('Index must be a number >= 0', 'ERROR')
|
printmsg('Index must be a number >= 0', 'ERROR')
|
||||||
bdb.close_quit(1)
|
bdb.close_quit(1)
|
||||||
elif int(args.update[0]) == 0:
|
|
||||||
bdb.refreshdb(0, titleManual)
|
|
||||||
else:
|
else:
|
||||||
if args.url is not None:
|
update_index = int(args.update[0])
|
||||||
new_url = args.url[0]
|
|
||||||
else:
|
|
||||||
new_url = ''
|
|
||||||
|
|
||||||
# Parse tags into a comma-separated string
|
if args.url is not None:
|
||||||
tags = parse_tags(tagManual)
|
new_url = args.url[0]
|
||||||
bdb.update_bookmark(int(args.update[0]), new_url, titleManual, tags, description)
|
else:
|
||||||
|
new_url = ''
|
||||||
|
|
||||||
|
# Parse tags into a comma-separated string
|
||||||
|
tags = parse_tags(tagManual)
|
||||||
|
|
||||||
|
bdb.update_bookmark(update_index, new_url, titleManual, tags, description)
|
||||||
|
|
||||||
# Delete record(s)
|
# Delete record(s)
|
||||||
if args.delete is not None:
|
if args.delete is not None:
|
||||||
|
2
buku.1
2
buku.1
@ -45,7 +45,7 @@ URLs are unique in DB. The same URL cannot be added twice. You can update tags a
|
|||||||
- -S : match all the keywords in URL, title or tags.
|
- -S : match all the keywords in URL, title or tags.
|
||||||
- --st : search bookmarks by tag, or show all tags alphabetically.
|
- --st : search bookmarks by tag, or show all tags alphabetically.
|
||||||
- You can search bookmarks by tag (see examples below).
|
- You can search bookmarks by tag (see examples below).
|
||||||
- Search results are indexed serially. This index is different from actual database index of a bookmark record which is shown within '[]' after the URL.
|
- Search results are indexed serially. This index is different from actual database index of a bookmark record which is shown in bold within '[]' after the URL.
|
||||||
.PP
|
.PP
|
||||||
Auto DB compaction: when a record is deleted, the last record is moved to the index.
|
Auto DB compaction: when a record is deleted, the last record is moved to the index.
|
||||||
.PP
|
.PP
|
||||||
|
93
tests/ci-test-wrapper
Executable file
93
tests/ci-test-wrapper
Executable file
@ -0,0 +1,93 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
declare here repo_root
|
||||||
|
here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
repo_root="$here/.."
|
||||||
|
export GIT_DIR="$here/../.git"
|
||||||
|
|
||||||
|
declare -a watchlist
|
||||||
|
watchlist=(buku tests)
|
||||||
|
while [[ $1 == -* ]]; do
|
||||||
|
case $1 in
|
||||||
|
-h|--help)
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage: ci-test-wrapper [-h|--help] [--monitor PATH [PATH ...]]
|
||||||
|
|
||||||
|
buku(1) testing wrapper for CIs.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help
|
||||||
|
Print this help and exit.
|
||||||
|
--watch PATH [PATH ...]
|
||||||
|
Additional paths (relative to repository root) to watch. Only run tests
|
||||||
|
when watched paths have been modified. By default only buku and
|
||||||
|
tests/ are watched, but sometimes additional paths should be watched
|
||||||
|
depending on circumstances, e.g., for Travis, .travis.yml should also
|
||||||
|
be watched. Note that this option consumes all of the remaining command
|
||||||
|
line arguments.
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
--watch)
|
||||||
|
shift
|
||||||
|
watchlist=( "${watchlist[@]}" "$@" )
|
||||||
|
shift $#
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
printf '\033[31mError: Unrecognized option %q.\033[0m\n' "$1" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
(( $# > 0 )) && {
|
||||||
|
printf '\033[31mError: Unrecognized arguments %s.\033[0m\n' "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Abort if the CI_SKIP_TEST environment variable is detected.
|
||||||
|
if [[ -n $CI_SKIP_TEST ]]; then
|
||||||
|
printf 'Detected $CI_SKIP_TEST. Skipping tests.' >&2
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Diff HEAD against a base commit to see if the changes are worth
|
||||||
|
# testing. (This check is skipped entirely if the CI_FORCE_TEST environment
|
||||||
|
# variable is set and non-nil.)
|
||||||
|
#
|
||||||
|
# * For a regular branch, diff against HEAD^;
|
||||||
|
# * For a PR branch, diff against the merge base of HEAD and master.
|
||||||
|
#
|
||||||
|
# Currently we use $TRAVIS_PULL_REQUEST to determine whether we're building a
|
||||||
|
# PR branch. Other criteria may be added if we ever expand to other CIs.
|
||||||
|
|
||||||
|
if [[ -z $CI_FORCE_TEST ]]; then
|
||||||
|
printf 'We are watching the following paths:\n' >&2
|
||||||
|
printf ' - %s\n' "${watchlist[@]}" >&2
|
||||||
|
printf '\n' >&2
|
||||||
|
|
||||||
|
declare diff_commits diff
|
||||||
|
if [[ -z ${TRAVIS_PULL_REQUEST+x} || $TRAVIS_PULL_REQUEST == false ]]; then
|
||||||
|
diff_commits='HEAD^..HEAD'
|
||||||
|
else
|
||||||
|
diff_commits='master...HEAD'
|
||||||
|
fi
|
||||||
|
diff=$(git -C "$repo_root" diff "$diff_commits" -- "${watchlist[@]}")
|
||||||
|
if [[ -z $diff ]]; then
|
||||||
|
printf 'None of the watchlist items changed, skipping tests.\n' >&2
|
||||||
|
printf 'You may set the $CI_FORCE_TEST environment variable to force testing.\n' >&2
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
printf 'Changes to watchlist item(s) detected. Will test.\n\n' >&2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
printf 'Detected $CI_FORCE_TEST. Skipping necessity checks.\n\n' >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test buku(1) with $repo_root at the beginning of $PATH (so that buku
|
||||||
|
# from this repo is picked up).
|
||||||
|
cd $here
|
||||||
|
PATH="$repo_root:$PATH" python -m pytest test_*.py
|
@ -1,5 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
tests_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
cd $tests_dir
|
|
||||||
python -m pytest test_*.py
|
|
276
tools/makedeb
Executable file
276
tools/makedeb
Executable file
@ -0,0 +1,276 @@
|
|||||||
|
#!/usr/bin/env zsh
|
||||||
|
|
||||||
|
# Automatically make .deb package from a commit or a tag.
|
||||||
|
#
|
||||||
|
# Prerequisites:
|
||||||
|
# zsh, build-essential, devscripts, debhelper (>= 9)
|
||||||
|
#
|
||||||
|
# Reference: https://wiki.debian.org/IntroDebianPackaging.
|
||||||
|
|
||||||
|
setopt errexit noshwordsplit nobashrematch
|
||||||
|
[[ -n $DEBUG ]] && setopt xtrace
|
||||||
|
|
||||||
|
################### SET UP ENVIRONMENT AND BASE DIRECTORIES ####################
|
||||||
|
|
||||||
|
[[ -z $DEBFULLNAME ]] && DEBFULLNAME='Arun Prakash Jana'
|
||||||
|
[[ -z $DEBEMAIL ]] && DEBEMAIL='engineerarun@gmail.com'
|
||||||
|
[[ -z $TZ ]] && TZ='Asia/Kolkata'
|
||||||
|
export DEBFULLNAME DEBEMAIL TZ
|
||||||
|
|
||||||
|
here=$0:A:h
|
||||||
|
repodir=$here/..
|
||||||
|
builddir=$here/../build
|
||||||
|
distdir=$here/../dist
|
||||||
|
|
||||||
|
export GIT_DIR=$repodir/.git
|
||||||
|
|
||||||
|
################################# SET UP TRAPS #################################
|
||||||
|
|
||||||
|
# Trap SIGUSR1: Abort program when functions called from within command
|
||||||
|
# substitutions in heredocs fail.
|
||||||
|
trap 'print_error "Encountered problem inside cmdsubst at line $LINENO."; exit 1' SIGUSR1
|
||||||
|
export NOTIFY_PID=$$
|
||||||
|
|
||||||
|
############################### HELPER FUNCTIONS ###############################
|
||||||
|
|
||||||
|
print_error () print -R $'\e[31m'"Error: $*"$'\e[0m' >&2
|
||||||
|
|
||||||
|
print_warning () print -R $'\e[33m'"Warning: $*"$'\e[0m' >&2
|
||||||
|
|
||||||
|
# Usage: apt_package_version <package_name>
|
||||||
|
apt_package_version () {
|
||||||
|
local version="${$(apt-cache show $1 | grep '^Version')#Version: }" || {
|
||||||
|
print_error "Version info not available for package ${(q-)1}."
|
||||||
|
[[ -n $NOTIFY_PID ]] && kill -SIGUSR1 $NOTIFY_PID
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
printf %s $version
|
||||||
|
}
|
||||||
|
|
||||||
|
debian_policy_version () {
|
||||||
|
local full_version="$(apt_package_version debian-policy)"
|
||||||
|
local match
|
||||||
|
[[ $full_version =~ ^(([0-9]+\.){2}[0-9]+) ]] || {
|
||||||
|
print_error "Invalid debian-policy version ${(q-)full_version}."
|
||||||
|
[[ -n $NOTIFY_PID ]] && kill -SIGUSR1 $NOTIFY_PID
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
printf %s $match[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Git helpers
|
||||||
|
|
||||||
|
# Usage: git_normalize_commitish <commit-ish>
|
||||||
|
#
|
||||||
|
# Normalize a commit-ish to a tag name if the commit-ish refers to a tag or
|
||||||
|
# tagged commit; otherwise to a SHA (via git-rev-parse).
|
||||||
|
git_normalize_commitish () {
|
||||||
|
local tagname commitsha
|
||||||
|
if tagname=$(git describe --exact --tags $1 2>/dev/null); then
|
||||||
|
printf %s $tagname
|
||||||
|
else
|
||||||
|
commitsha=$(git rev-parse --verify --quite $1) || {
|
||||||
|
print_error "Unable to parse ${(q-)1} as a git commit."
|
||||||
|
[[ -n $NOTIFY_PID ]] && kill -SIGUSR1 $NOTIFY_PID
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
printf %s $commitsha
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage: git_ref_is_tag <refname>
|
||||||
|
#
|
||||||
|
# Returns 0 (is tag) or 1 (not tag).
|
||||||
|
git_ref_is_tag () {
|
||||||
|
git show-ref --quiet --verify refs/tags/$1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage: git_commitish_timestamp <normalized_commitish>
|
||||||
|
#
|
||||||
|
# Expects a normalized commit-ish (see git_normalize_commitish) as input, and
|
||||||
|
# outputs a timestamp. For a tag, the timestamp is the tagger date. For a
|
||||||
|
# commit, the timestamp is the committer date.
|
||||||
|
git_commitish_timestamp () {
|
||||||
|
if git_ref_is_tag $1; then
|
||||||
|
local date="$(git for-each-ref --format='%(taggerdate)' refs/tags/$1)"
|
||||||
|
|
||||||
|
# The date returned by git-for-each-ref looks like `Sat Apr 23 10:38:27
|
||||||
|
# 2016 +0530', which isn't recognized by date(1) from coreutils. Need a
|
||||||
|
# hack to turn `+0530' into `U+0530' (same for -).
|
||||||
|
#
|
||||||
|
# Note that date will be empty if the tag at question is a lightweight
|
||||||
|
# tag (i.e., non-annotated) because they don't carry any tagger
|
||||||
|
# information; in that case we simply fall back to the committer.
|
||||||
|
if [[ -n $date ]]; then
|
||||||
|
date -d ${${date// -/ U-}// +/ U+} +%s
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
git rev-list --format=format:%ct --max-count=1 $1 | tail -n1
|
||||||
|
}
|
||||||
|
|
||||||
|
######################### PARSE COMMAND LINE ARGUMENTS #########################
|
||||||
|
|
||||||
|
tag_only=0
|
||||||
|
while [[ $1 == -* ]]; do
|
||||||
|
case $1 in
|
||||||
|
-h|--help)
|
||||||
|
cat >&2 <<EOF
|
||||||
|
Usage: $0:t [options] [<commit-ish>]
|
||||||
|
|
||||||
|
Make a deb package from a git commit-ish, which defaults to HEAD.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help
|
||||||
|
Print this help and exit.
|
||||||
|
--tag-only
|
||||||
|
Only make deb if HEAD (or <commit-ish>, if specified) is a tag or a
|
||||||
|
tagged commit.
|
||||||
|
EOF
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
--tag-only)
|
||||||
|
tag_only=1
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
print_error "Unknown option ${(q-)1}."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ -n $1 ]] && { commitish=$1; shift } || commitish=HEAD
|
||||||
|
(( $# > 0 )) && {
|
||||||
|
print_error 'Unrecognized arguments' ${(q-)@}
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
##################################### MAIN #####################################
|
||||||
|
|
||||||
|
mkdir -p $builddir $distdir
|
||||||
|
cd $builddir
|
||||||
|
|
||||||
|
normalized_commitish=$(git_normalize_commitish $commitish)
|
||||||
|
git_ref_is_tag $normalized_commitish && commitish_is_tag=1 || commitish_is_tag=0
|
||||||
|
|
||||||
|
(( tag_only && !commitish_is_tag )) && {
|
||||||
|
print_warning "${(q-)commitish} is not a tag or tagged commit, skipping build."
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
pkgname=buku
|
||||||
|
version="${$(git describe --tags $commitish)#v}" # Quoting just to make sh-mode happy
|
||||||
|
[[ -n $version ]] || {
|
||||||
|
print_error 'Failed to extract version information.'
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
debrevision=1
|
||||||
|
creation_timestamp=$(git_commitish_timestamp $normalized_commitish)
|
||||||
|
|
||||||
|
upstream_tarball=$builddir/${pkgname}_${version}.orig.tar.gz
|
||||||
|
buildsubdirname=${pkgname}-${version}
|
||||||
|
git -C $repodir archive --format=tar.gz --prefix=$buildsubdirname/ --output=$upstream_tarball $commitish .
|
||||||
|
rm -rf $buildsubdirname
|
||||||
|
tar xf $upstream_tarball
|
||||||
|
|
||||||
|
cd $buildsubdirname
|
||||||
|
mkdir debian
|
||||||
|
|
||||||
|
# Write debian/changelog
|
||||||
|
|
||||||
|
if (( commitish_is_tag )); then
|
||||||
|
# Tag -- point to the release
|
||||||
|
changelog_url=https://github.com/jarun/Buku/releases/tag/$normalized_commitish
|
||||||
|
else
|
||||||
|
# Just a commit -- point to the list of commits in the tree
|
||||||
|
changelog_url=https://github.com/jarun/Buku/commits/$normalized_commitish
|
||||||
|
fi
|
||||||
|
cat >debian/changelog <<EOF
|
||||||
|
$pkgname (${version}-${debrevision}) UNRELEASED; urgency=medium
|
||||||
|
|
||||||
|
* See full changelog at
|
||||||
|
$changelog_url
|
||||||
|
|
||||||
|
-- $DEBFULLNAME <$DEBEMAIL> $(date --rfc-2822 --date=@$creation_timestamp)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Alternatively, use dch to create changelog interactively:
|
||||||
|
# dch --create -v ${version}-${debrevision} --package $pkgname
|
||||||
|
|
||||||
|
# Write debian/compat
|
||||||
|
cat >debian/compat <<'EOF'
|
||||||
|
9
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Write debian/control
|
||||||
|
cat >debian/control <<EOF
|
||||||
|
Source: $pkgname
|
||||||
|
Maintainer: $DEBFULLNAME <$DEBEMAIL>
|
||||||
|
Section: misc
|
||||||
|
Priority: optional
|
||||||
|
Standards-Version: $(debian_policy_version)
|
||||||
|
Build-Depends: debhelper (>= 9)
|
||||||
|
|
||||||
|
Package: $pkgname
|
||||||
|
Architecture: all
|
||||||
|
Depends: \${shlibs:Depends}, \${misc:Depends}, python3 (>= 3.3), python3-cryptography, python3-bs4
|
||||||
|
Description: Powerful command-line bookmark manager
|
||||||
|
See https://github.com/jarun/Buku#readme.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Write debian/copyright
|
||||||
|
copyright_file=$builddir/$buildsubdirname/debian/copyright
|
||||||
|
cat >debian/copyright <<EOF
|
||||||
|
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: $pkgname
|
||||||
|
Upstream-Contact: $DEBFULLNAME <$DEBEMAIL>
|
||||||
|
Source: https://github.com/jarun/Buku
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2015, 2016 Arun Prakash Jana
|
||||||
|
License: GPL-3
|
||||||
|
This program is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License version 3 as published by the Free
|
||||||
|
Software Foundation.
|
||||||
|
.
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||||
|
details.
|
||||||
|
.
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
.
|
||||||
|
On Debian systems, the full text of the GNU General Public License version 3
|
||||||
|
can be found in the file '/usr/share/common-licenses/GPL-3'.
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Write debian/rules
|
||||||
|
cat >debian/rules <<EOF
|
||||||
|
#!/usr/bin/make -f
|
||||||
|
%:
|
||||||
|
dh \$@
|
||||||
|
|
||||||
|
override_dh_auto_install:
|
||||||
|
\$(MAKE) DESTDIR=\$\$(pwd)/debian/$pkgname PREFIX=/usr install
|
||||||
|
cp -p ${(q-)copyright_file} \$\$(pwd)/debian/$pkgname/usr/share/doc/$pkgname/copyright
|
||||||
|
EOF
|
||||||
|
chmod +x debian/rules
|
||||||
|
|
||||||
|
# Write debian/source/format
|
||||||
|
mkdir -p debian/source
|
||||||
|
cat >debian/source/format <<'EOF'
|
||||||
|
3.0 (quilt)
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Build binary package
|
||||||
|
debuild -us -uc
|
||||||
|
|
||||||
|
# Copying deb to dist
|
||||||
|
binary_package=$builddir/${pkgname}_${version}-${debrevision}_all.deb
|
||||||
|
cp -p $binary_package $distdir
|
Loading…
Reference in New Issue
Block a user