lg 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in memories.gemspec
4
+ gemspec
@@ -0,0 +1,20 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'minitest' do
5
+
6
+ # with Minitest::Spec
7
+ watch(%r|^spec/(.*)_spec\.rb|)
8
+ watch(%r|^lib/(.*)([^/]+)\.rb|) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
9
+ watch(%r|^spec/spec_helper\.rb|) { "spec" }
10
+
11
+ # Rails 3.2
12
+ # watch(%r|^app/controllers/(.*)\.rb|) { |m| "test/controllers/#{m[1]}_test.rb" }
13
+ # watch(%r|^app/helpers/(.*)\.rb|) { |m| "test/helpers/#{m[1]}_test.rb" }
14
+ # watch(%r|^app/models/(.*)\.rb|) { |m| "test/unit/#{m[1]}_test.rb" }
15
+
16
+ # Rails
17
+ # watch(%r|^app/controllers/(.*)\.rb|) { |m| "test/functional/#{m[1]}_test.rb" }
18
+ # watch(%r|^app/helpers/(.*)\.rb|) { |m| "test/helpers/#{m[1]}_test.rb" }
19
+ # watch(%r|^app/models/(.*)\.rb|) { |m| "test/unit/#{m[1]}_test.rb" }
20
+ end
@@ -0,0 +1,117 @@
1
+ # Logbook
2
+
3
+ Logbook allows you to record memories easily from your command line into
4
+ virtual book(s). Books are simply private Github Gists (backend is
5
+ replaceable).
6
+
7
+
8
+ It is heavily inspired from its pythonish friend, http://maebert.github.com/jrnl.
9
+
10
+ I built it because I love Ruby, it was easy enough, and I really loved
11
+ the idea of storing as Gists as opposed to plain files.
12
+
13
+
14
+
15
+ # Usage
16
+
17
+ For brevity's sake, the Logbook gem name and executable is `lg`.
18
+
19
+ $ gem install lg
20
+ $ lg
21
+
22
+
23
+ If you want private Gists attached to your user (you most probably
24
+ want that), make sure to set your Github credentials as environment
25
+ variables, example:
26
+
27
+ $ export GITHUB_USER=youruser
28
+ $ export GITHUB_PASSWORD=yourpw
29
+
30
+ Now we need to make a first `book` and start `add`ing into it.
31
+
32
+ ## Setting up a book
33
+
34
+ Create a new book with the `lg book` command. You can give it a
35
+ cover, in this case `The Wizzard of Oz`.
36
+
37
+ $ lg book The Wizzard of Oz
38
+
39
+
40
+ ## Adding lgries
41
+
42
+ Simply say 'lg add' and your memory in a short sentence.
43
+
44
+ $ lg add just wrote the logbook gem README
45
+
46
+ You might find it convenient to specify when a thing happend explicitly,
47
+ just make sure to specify a natural date such as `yesterday` separated
48
+ by a colon `:`. Translation done with the `chronic` gem.
49
+
50
+ $ lg add yesterday: wrote the logbook gem README
51
+
52
+
53
+ ## More
54
+
55
+ You can safely skip this if that's all what you're looking for.
56
+
57
+ ## Switching books
58
+
59
+ Switch between books, when you know what you want, you can explicitly
60
+ specify the ID.
61
+
62
+ $ lg book book-id
63
+
64
+ Or pick from a menu, leaving arguments blank:
65
+
66
+ $ lg book
67
+ 1 The Wizzard of Oz deadbeef0aef
68
+ ...
69
+ Pick one: 1
70
+
71
+
72
+ ## Listing lgries
73
+
74
+ Say `lg all` when you want to see everything you've recorded.
75
+
76
+
77
+
78
+
79
+ # Philosophy
80
+
81
+ Command line is awesome. Its fast, and you feel it when you're less
82
+ dependent on your mouse for your development work (e.g. VIM).
83
+
84
+ You should just Alt/Command-Tab, write a line and go back working.
85
+
86
+ You should be expected to remember at most one commands (pitfall of success) to do actual work. Seriously, [focus](http://ezliu.com/focus/).
87
+
88
+
89
+ ## There's no search like in jrnl
90
+
91
+ Feature slim. Use gist search for that. True, its limited, but as of now, I believe
92
+ Github are working on improving that.
93
+
94
+ In actuallity, `jrnl`'s search loads all of your entries to memory and
95
+ performs search on an in-memory structure.
96
+ If the need arises, it should be dead easy to
97
+ make *that* kind of search in `logbook`.
98
+
99
+ ## There's no delete/modify
100
+
101
+ Again, feature slim. If you were using a real logbook, you'd
102
+ just cross the bad entry. It will still be there.
103
+ If you must, you can always use the gist interface for that.
104
+
105
+ ## There's no analytics, let me reap added value from my work!
106
+
107
+ Actually, a gist entry is a Git repository.
108
+ The modeling on-top-of a
109
+ Gist was done intentionally. Clone your book and
110
+ treat it like a Git repo.
111
+
112
+ From there, you can script against git and/or run countless analysis tools on your repository.
113
+
114
+
115
+
116
+
117
+
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/lg ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ require "logbook/cli"
3
+
4
+
5
+ # banner
6
+ # testing:
7
+ # cli 'all'
8
+ # pr:
9
+ # logo
10
+ #
11
+
12
+ Logbook::CLI.start
13
+
@@ -0,0 +1,116 @@
1
+ Certificate chain
2
+ 0 s:/O=*.github.com/OU=Domain Control Validated/CN=*.github.com
3
+ i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=07969287
4
+ -----BEGIN CERTIFICATE-----
5
+ MIIFVTCCBD2gAwIBAgIHBGX+dPs18DANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
6
+ BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY
7
+ BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm
8
+ aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5
9
+ IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky
10
+ ODcwHhcNMDkxMjExMDUwMjM2WhcNMTQxMjExMDUwMjM2WjBRMRUwEwYDVQQKEwwq
11
+ LmdpdGh1Yi5jb20xITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEV
12
+ MBMGA1UEAxMMKi5naXRodWIuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
13
+ CgKCAQEA7dOJw11wcgnzM08acnTZtlqVULtoYZ/3+x8Z4doEMa8VfBp/+XOvHeVD
14
+ K1YJAEVpSujEW9/Cd1JRGVvRK9k5ZTagMhkcQXP7MrI9n5jsglsLN2Q5LLcQg3LN
15
+ 8OokS/rZlC7DhRU5qTr2iNr0J4mmlU+EojdOfCV4OsmDbQIXlXh9R6hVg+4TyBka
16
+ szzxX/47AuGF+xFmqwldn0xD8MckXilyKM7UdWhPJHIprjko/N+NT02Dc3QMbxGb
17
+ p91i3v/i6xfm/wy/wC0xO9ZZovLdh0pIe20zERRNNJ8yOPbIGZ3xtj3FRu9RC4rG
18
+ M+1IYcQdFxu9fLZn6TnPpVKACvTqzQIDAQABo4IBtjCCAbIwDwYDVR0TAQH/BAUw
19
+ AwEBADAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDgYDVR0PAQH/BAQD
20
+ AgWgMDMGA1UdHwQsMCowKKAmoCSGImh0dHA6Ly9jcmwuZ29kYWRkeS5jb20vZ2Rz
21
+ MS0xMS5jcmwwUwYDVR0gBEwwSjBIBgtghkgBhv1tAQcXATA5MDcGCCsGAQUFBwIB
22
+ FitodHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkvMIGA
23
+ BggrBgEFBQcBAQR0MHIwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmdvZGFkZHku
24
+ Y29tLzBKBggrBgEFBQcwAoY+aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNv
25
+ bS9yZXBvc2l0b3J5L2dkX2ludGVybWVkaWF0ZS5jcnQwHwYDVR0jBBgwFoAU/axh
26
+ MpNsRdbi7oVfmrrndplozOcwIwYDVR0RBBwwGoIMKi5naXRodWIuY29tggpnaXRo
27
+ dWIuY29tMB0GA1UdDgQWBBSH0Y8ZbuSHb1OMd5EHUN+jv1VHIDANBgkqhkiG9w0B
28
+ AQUFAAOCAQEAwIe/Bbuk1/r38aqb5wlXjoW6tAmLpzLRkKorDOcDUJLtN6a9XqAk
29
+ cgMai7NCI1YV+A4IjEENj53mV2xWLpniqLDHI5y2NbQuL2deu1jQSSNz7xE/nZCk
30
+ WGt8OEtm6YI2bUsq5EXy078avRbigBko1bqtFuG0s5+nFrKCjhQVIk+GX7cwiyr4
31
+ XJ49FxETvePrxNYr7x7n/Jju59KXTw3juPET+bAwNlRXmScjrMylMNUMr3sFcyLz
32
+ DciaVnnextu6+L0w1+5KNVbMKndRwgg/cRldBL4AgmtouTC3mlDGGG3U6eV75cdH
33
+ D03DXDfrYYjxmWjTRdO2GdbYnt1ToEgxyA==
34
+ -----END CERTIFICATE-----
35
+ 1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certificates.godaddy.com/repository/CN=Go Daddy Secure Certification Authority/serialNumber=07969287
36
+ i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
37
+ -----BEGIN CERTIFICATE-----
38
+ MIIE3jCCA8agAwIBAgICAwEwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCVVMx
39
+ ITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
40
+ RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMTYw
41
+ MTU0MzdaFw0yNjExMTYwMTU0MzdaMIHKMQswCQYDVQQGEwJVUzEQMA4GA1UECBMH
42
+ QXJpem9uYTETMBEGA1UEBxMKU2NvdHRzZGFsZTEaMBgGA1UEChMRR29EYWRkeS5j
43
+ b20sIEluYy4xMzAxBgNVBAsTKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5j
44
+ b20vcmVwb3NpdG9yeTEwMC4GA1UEAxMnR28gRGFkZHkgU2VjdXJlIENlcnRpZmlj
45
+ YXRpb24gQXV0aG9yaXR5MREwDwYDVQQFEwgwNzk2OTI4NzCCASIwDQYJKoZIhvcN
46
+ AQEBBQADggEPADCCAQoCggEBAMQt1RWMnCZM7DI161+4WQFapmGBWTtwY6vj3D3H
47
+ KrjJM9N55DrtPDAjhI6zMBS2sofDPZVUBJ7fmd0LJR4h3mUpfjWoqVTr9vcyOdQm
48
+ VZWt7/v+WIbXnvQAjYwqDL1CBM6nPwT27oDyqu9SoWlm2r4arV3aLGbqGmu75RpR
49
+ SgAvSMeYddi5Kcju+GZtCpyz8/x4fKL4o/K1w/O5epHBp+YlLpyo7RJlbmr2EkRT
50
+ cDCVw5wrWCs9CHRK8r5RsL+H0EwnWGu1NcWdrxcx+AuP7q2BNgWJCJjPOq8lh8BJ
51
+ 6qf9Z/dFjpfMFDniNoW1fho3/Rb2cRGadDAW/hOUoz+EDU8CAwEAAaOCATIwggEu
52
+ MB0GA1UdDgQWBBT9rGEyk2xF1uLuhV+auud2mWjM5zAfBgNVHSMEGDAWgBTSxLDS
53
+ kdRMEXGzYcs9of7dqGrU4zASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUFBwEB
54
+ BCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZ29kYWRkeS5jb20wRgYDVR0f
55
+ BD8wPTA7oDmgN4Y1aHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNvbS9yZXBv
56
+ c2l0b3J5L2dkcm9vdC5jcmwwSwYDVR0gBEQwQjBABgRVHSAAMDgwNgYIKwYBBQUH
57
+ AgEWKmh0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeTAO
58
+ BgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBANKGwOy9+aG2Z+5mC6IG
59
+ OgRQjhVyrEp0lVPLN8tESe8HkGsz2ZbwlFalEzAFPIUyIXvJxwqoJKSQ3kbTJSMU
60
+ A2fCENZvD117esyfxVgqwcSeIaha86ykRvOe5GPLL5CkKSkB2XIsKd83ASe8T+5o
61
+ 0yGPwLPk9Qnt0hCqU7S+8MxZC9Y7lhyVJEnfzuz9p0iRFEUOOjZv2kWzRaJBydTX
62
+ RE4+uXR21aITVSzGh6O1mawGhId/dQb8vxRMDsxuxN89txJx9OjxUUAiKEngHUuH
63
+ qDTMBqLdElrRhjZkAzVvb3du6/KFUJheqwNTrZEjYx8WnM25sgVjOuH0aBsXBTWV
64
+ U+4=
65
+ -----END CERTIFICATE-----
66
+ 2 s:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
67
+ i:/L=ValiCert Validation Network/O=ValiCert, Inc./OU=ValiCert Class 2 Policy Validation Authority/CN=http://www.valicert.com//emailAddress=info@valicert.com
68
+ -----BEGIN CERTIFICATE-----
69
+ MIIE+zCCBGSgAwIBAgICAQ0wDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1Zh
70
+ bGlDZXJ0IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIElu
71
+ Yy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24g
72
+ QXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAe
73
+ BgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTA0MDYyOTE3MDYyMFoX
74
+ DTI0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBE
75
+ YWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3MgMiBDZXJ0
76
+ aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgC
77
+ ggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
78
+ 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+q
79
+ N1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiO
80
+ r18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lN
81
+ f4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+YihfukEH
82
+ U1jPEX44dMX4/7VpkI+EdOqXG68CAQOjggHhMIIB3TAdBgNVHQ4EFgQU0sSw0pHU
83
+ TBFxs2HLPaH+3ahq1OMwgdIGA1UdIwSByjCBx6GBwaSBvjCBuzEkMCIGA1UEBxMb
84
+ VmFsaUNlcnQgVmFsaWRhdGlvbiBOZXR3b3JrMRcwFQYDVQQKEw5WYWxpQ2VydCwg
85
+ SW5jLjE1MDMGA1UECxMsVmFsaUNlcnQgQ2xhc3MgMiBQb2xpY3kgVmFsaWRhdGlv
86
+ biBBdXRob3JpdHkxITAfBgNVBAMTGGh0dHA6Ly93d3cudmFsaWNlcnQuY29tLzEg
87
+ MB4GCSqGSIb3DQEJARYRaW5mb0B2YWxpY2VydC5jb22CAQEwDwYDVR0TAQH/BAUw
88
+ AwEB/zAzBggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmdv
89
+ ZGFkZHkuY29tMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jZXJ0aWZpY2F0ZXMu
90
+ Z29kYWRkeS5jb20vcmVwb3NpdG9yeS9yb290LmNybDBLBgNVHSAERDBCMEAGBFUd
91
+ IAAwODA2BggrBgEFBQcCARYqaHR0cDovL2NlcnRpZmljYXRlcy5nb2RhZGR5LmNv
92
+ bS9yZXBvc2l0b3J5MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOBgQC1
93
+ QPmnHfbq/qQaQlpE9xXUhUaJwL6e4+PrxeNYiY+Sn1eocSxI0YGyeR+sBjUZsE4O
94
+ WBsUs5iB0QQeyAfJg594RAoYC5jcdnplDQ1tgMQLARzLrUc+cb53S8wGd9D0Vmsf
95
+ SxOaFIqII6hR8INMqzW/Rn453HWkrugp++85j09VZw==
96
+ -----END CERTIFICATE-----
97
+ 3 s:/L=ValiCert Validation Network/O=ValiCert, Inc./OU=ValiCert Class 2 Policy Validation Authority/CN=http://www.valicert.com//emailAddress=info@valicert.com
98
+ i:/L=ValiCert Validation Network/O=ValiCert, Inc./OU=ValiCert Class 2 Policy Validation Authority/CN=http://www.valicert.com//emailAddress=info@valicert.com
99
+ -----BEGIN CERTIFICATE-----
100
+ MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
101
+ IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
102
+ BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
103
+ aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
104
+ 9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
105
+ NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
106
+ azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
107
+ YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
108
+ Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
109
+ cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
110
+ dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
111
+ WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
112
+ v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
113
+ UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
114
+ IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
115
+ W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
116
+ -----END CERTIFICATE-----
@@ -0,0 +1,255 @@
1
+ require 'gist_store/net_http_ext'
2
+ require 'open-uri'
3
+ require 'net/https'
4
+ require 'optparse'
5
+ require 'json'
6
+ require 'base64'
7
+
8
+
9
+
10
+ # You can use this class from other scripts with the greatest of
11
+ # ease.
12
+ #
13
+ # >> Gist.read(gist_id)
14
+ # Returns the body of gist_id as a string.
15
+ #
16
+ # >> Gist.write(content)
17
+ # Creates a gist from the string `content`. Returns the URL of the
18
+ # new gist.
19
+ #
20
+ # >> Gist.copy(string)
21
+ # Copies string to the clipboard.
22
+ #
23
+ # >> Gist.browse(url)
24
+ # Opens URL in your default browser.
25
+ module Gist
26
+ extend self
27
+
28
+ GIST_URL = 'https://api.github.com/gists/%s'
29
+ CREATE_URL = 'https://api.github.com/gists'
30
+
31
+ if ENV['HTTPS_PROXY']
32
+ PROXY = URI(ENV['HTTPS_PROXY'])
33
+ elsif ENV['HTTP_PROXY']
34
+ PROXY = URI(ENV['HTTP_PROXY'])
35
+ else
36
+ PROXY = nil
37
+ end
38
+ PROXY_HOST = PROXY ? PROXY.host : nil
39
+ PROXY_PORT = PROXY ? PROXY.port : nil
40
+
41
+
42
+ # Create a gist on gist.github.com
43
+ def write(files, private_gist = false, description = nil)
44
+ url = URI.parse(CREATE_URL)
45
+
46
+ if PROXY_HOST
47
+ proxy = Net::HTTP::Proxy(PROXY_HOST, PROXY_PORT)
48
+ http = proxy.new(url.host, url.port)
49
+ else
50
+ http = Net::HTTP.new(url.host, url.port)
51
+ end
52
+
53
+ http.use_ssl = true
54
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
55
+ http.ca_file = ca_cert
56
+
57
+ req = Net::HTTP::Post.new(url.path)
58
+ req.body = JSON.generate(data(files, private_gist, description))
59
+
60
+ user, password = auth()
61
+ if user && password
62
+ req.basic_auth(user, password)
63
+ end
64
+
65
+ response = http.start{|h| h.request(req) }
66
+ case response
67
+ when Net::HTTPCreated
68
+ JSON.parse(response.body)['html_url']
69
+ else
70
+ raise "Creating gist failed: #{response.code} #{response.message}"
71
+ end
72
+ end
73
+
74
+ # Create a gist on gist.github.com
75
+ def update(id, files)
76
+ url = URI.parse(CREATE_URL)
77
+
78
+ if PROXY_HOST
79
+ proxy = Net::HTTP::Proxy(PROXY_HOST, PROXY_PORT)
80
+ http = proxy.new(url.host, url.port)
81
+ else
82
+ http = Net::HTTP.new(url.host, url.port)
83
+ end
84
+
85
+ http.use_ssl = true
86
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
87
+ http.ca_file = ca_cert
88
+
89
+ req = Net::HTTP::Patch.new(GIST_URL % id)
90
+ req.body = JSON.generate(data(files, nil, nil))
91
+
92
+ user, password = auth()
93
+ if user && password
94
+ req.basic_auth(user, password)
95
+ end
96
+
97
+ response = http.start{|h| h.request(req) }
98
+ case response
99
+ when Net::HTTPOK
100
+ JSON.parse(response.body)['html_url']
101
+ else
102
+ raise "Updating gist failed: #{response.code} #{response.message}"
103
+ end
104
+ end
105
+
106
+
107
+
108
+ # Create a gist on gist.github.com
109
+ def delete(id)
110
+ url = URI.parse(CREATE_URL)
111
+
112
+ if PROXY_HOST
113
+ proxy = Net::HTTP::Proxy(PROXY_HOST, PROXY_PORT)
114
+ http = proxy.new(url.host, url.port)
115
+ else
116
+ http = Net::HTTP.new(url.host, url.port)
117
+ end
118
+
119
+ http.use_ssl = true
120
+ http.verify_mode = OpenSSL::SSL::VERIFY_PEER
121
+ http.ca_file = ca_cert
122
+
123
+ req = Net::HTTP::Delete.new(GIST_URL % id)
124
+
125
+ user, password = auth()
126
+ if user && password
127
+ req.basic_auth(user, password)
128
+ end
129
+
130
+ response = http.start{|h| h.request(req) }
131
+ case response
132
+ when Net::HTTPNoContent
133
+ true
134
+ else
135
+ raise "Creating gist failed: #{response.code} #{response.message}"
136
+ end
137
+ end
138
+
139
+ # Given a gist id, returns its content.
140
+ def read(gist_id)
141
+ data = read_raw(gist_id)
142
+ data["files"].map{|name, content| content['content'] }.join("\n\n")
143
+ end
144
+
145
+ def read_raw(gist_id)
146
+ data = JSON.parse(open(GIST_URL % gist_id).read)
147
+ end
148
+
149
+
150
+ private
151
+ # Give an array of file information and private boolean, returns
152
+ # an appropriate payload for POSTing to gist.github.com
153
+ def data(files, private_gist, description)
154
+ i = 0
155
+ file_data = {}
156
+ files.each do |file|
157
+ i = i + 1
158
+ filename = file[:filename] ? file[:filename] : "gistfile#{i}"
159
+ file_data[filename] = {:content => file[:input]}
160
+ end
161
+
162
+ data = {"files" => file_data}
163
+ data.merge!({ 'description' => description }) unless description.nil?
164
+ data.merge!({ 'public' => !private_gist }) unless private_gist.nil?
165
+ data
166
+ end
167
+
168
+ # Returns a basic auth string of the user's GitHub credentials if set.
169
+ # http://github.com/guides/local-github-config
170
+ #
171
+ # Returns an Array of Strings if auth is found: [user, password]
172
+ # Returns nil if no auth is found.
173
+ def auth
174
+ user = config("github.user")
175
+ password = config("github.password")
176
+
177
+ token = config("github.token")
178
+ if password.to_s.empty? && !token.to_s.empty?
179
+ raise "Please set GITHUB_PASSWORD or github.password instead of using a token."
180
+ end
181
+
182
+ if user.to_s.empty? || password.to_s.empty?
183
+ nil
184
+ else
185
+ [ user, password ]
186
+ end
187
+ end
188
+
189
+ # Returns default values based on settings in your gitconfig. See
190
+ # git-config(1) for more information.
191
+ #
192
+ # Settings applicable to gist.rb are:
193
+ #
194
+ # gist.private - boolean
195
+ # gist.extension - string
196
+ def defaults
197
+ extension = config("gist.extension")
198
+
199
+ return {
200
+ "private" => config("gist.private"),
201
+ "browse" => config("gist.browse"),
202
+ "extension" => extension
203
+ }
204
+ end
205
+
206
+ # Reads a config value using:
207
+ # => Environment: GITHUB_PASSWORD, GITHUB_USER
208
+ # like vim gist plugin
209
+ # => git-config(1)
210
+ #
211
+ # return something useful or nil
212
+ def config(key)
213
+ env_key = ENV[key.upcase.gsub(/\./, '_')]
214
+ return env_key if env_key and not env_key.strip.empty?
215
+
216
+ str_to_bool `git config --global #{key}`.strip
217
+ end
218
+
219
+ # Parses a value that might appear in a .gitconfig file into
220
+ # something useful in a Ruby script.
221
+ def str_to_bool(str)
222
+ if str.size > 0 and str[0].chr == '!'
223
+ command = str[1, str.length]
224
+ value = `#{command}`
225
+ else
226
+ value = str
227
+ end
228
+
229
+ case value.downcase.strip
230
+ when "false", "0", "nil", "", "no", "off"
231
+ nil
232
+ when "true", "1", "yes", "on"
233
+ true
234
+ else
235
+ value
236
+ end
237
+ end
238
+
239
+ def ca_cert
240
+ cert_file = [
241
+ File.expand_path("../cacert.pem", __FILE__),
242
+ "/tmp/gist_cacert.pem"
243
+ ].find{|l| File.exist?(l) }
244
+
245
+ if cert_file
246
+ cert_file
247
+ else
248
+ File.open("/tmp/gist_cacert.pem", "w") do |f|
249
+ f.write(DATA.read.split("__CACERT__").last)
250
+ end
251
+ "/tmp/gist_cacert.pem"
252
+ end
253
+ end
254
+
255
+ end