mirror of
https://github.com/jlengrand/github-api.git
synced 2026-03-11 08:21:23 +00:00
Compare commits
721 Commits
github-api
...
github-api
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eff48dfe67 | ||
|
|
0c38bdc068 | ||
|
|
b8e1736696 | ||
|
|
c2f36444d0 | ||
|
|
5dc74f5b4d | ||
|
|
9694dfe4cc | ||
|
|
734125ea14 | ||
|
|
438f5d1b87 | ||
|
|
fadd6d7978 | ||
|
|
5026262273 | ||
|
|
5b53fba020 | ||
|
|
3892e6e16f | ||
|
|
33467de763 | ||
|
|
f3528d97c2 | ||
|
|
6fb3b01bf0 | ||
|
|
e3c9cec440 | ||
|
|
0e011425fb | ||
|
|
ba658f7fea | ||
|
|
0e6087143b | ||
|
|
5f967e6307 | ||
|
|
2eb8ce632c | ||
|
|
f25dbd15d9 | ||
|
|
cc5ea77170 | ||
|
|
e323644af2 | ||
|
|
61f3a3219f | ||
|
|
4dcf5dbc13 | ||
|
|
8faecba0a2 | ||
|
|
739551cbe3 | ||
|
|
24a2e42881 | ||
|
|
6921754c99 | ||
|
|
d8827a0b44 | ||
|
|
a48091988f | ||
|
|
9bd9c9cf1f | ||
|
|
695692285b | ||
|
|
03edacf7b6 | ||
|
|
4802c97e89 | ||
|
|
9fc24d1981 | ||
|
|
d4ddf453b0 | ||
|
|
c0117f07cf | ||
|
|
8a88c14b13 | ||
|
|
a5b6302a69 | ||
|
|
9f29d4619d | ||
|
|
f4b9dd7d7b | ||
|
|
c0a4152b00 | ||
|
|
efb87c5a9e | ||
|
|
061e8bb662 | ||
|
|
a4f42b2948 | ||
|
|
cb2fcd3a9e | ||
|
|
1d004a35a0 | ||
|
|
c763c02018 | ||
|
|
eb36cb4436 | ||
|
|
72d4b9bf62 | ||
|
|
81ea138f41 | ||
|
|
1bbc66ad62 | ||
|
|
e7348df372 | ||
|
|
550e060647 | ||
|
|
2970a58e95 | ||
|
|
e0efa04fd4 | ||
|
|
4d24088982 | ||
|
|
baba9f5de6 | ||
|
|
c35cd63d0e | ||
|
|
80fa389ce3 | ||
|
|
8ec861c9fe | ||
|
|
837400fb5e | ||
|
|
ec4525b8ff | ||
|
|
281c927971 | ||
|
|
9dd44c13e4 | ||
|
|
f28edbcf8f | ||
|
|
29e147f992 | ||
|
|
830f4231e1 | ||
|
|
7d65e31055 | ||
|
|
dec7a91b5b | ||
|
|
1ba630c221 | ||
|
|
7d3387fb96 | ||
|
|
a0c0de28d7 | ||
|
|
dc31d52f83 | ||
|
|
620c822dac | ||
|
|
5990f5ae22 | ||
|
|
37329a50d4 | ||
|
|
550597f72e | ||
|
|
2aa4022e2c | ||
|
|
b40741b14d | ||
|
|
3c739d889e | ||
|
|
24a92a133e | ||
|
|
ce97eb5b40 | ||
|
|
7a4e3c480e | ||
|
|
eefa710839 | ||
|
|
4c3e1afcca | ||
|
|
c1a77ada5d | ||
|
|
5671e5ed67 | ||
|
|
2fdc5a8541 | ||
|
|
297dbae247 | ||
|
|
0910cdf3a4 | ||
|
|
6877fb5c74 | ||
|
|
2d65daa8c9 | ||
|
|
dab4cb6186 | ||
|
|
40773a2b49 | ||
|
|
7e0d61a6fc | ||
|
|
7f9620d75f | ||
|
|
3559aef1a1 | ||
|
|
94ceb5eaaf | ||
|
|
778ca76d22 | ||
|
|
b1c0e41c5c | ||
|
|
f826edd097 | ||
|
|
edc7c4a4b8 | ||
|
|
dafdc66d25 | ||
|
|
0d135f14bb | ||
|
|
568c08d0e9 | ||
|
|
87410e295e | ||
|
|
b163e68950 | ||
|
|
88b006e957 | ||
|
|
477f2f2814 | ||
|
|
933d99c23b | ||
|
|
d3a0c5ded1 | ||
|
|
1e173ddc24 | ||
|
|
ca404cb33b | ||
|
|
f0dc7d5b02 | ||
|
|
933702376f | ||
|
|
e08896775b | ||
|
|
d610e46f8e | ||
|
|
7d1989f5a2 | ||
|
|
5c1e371427 | ||
|
|
dbd9d51747 | ||
|
|
fdf5d3f72d | ||
|
|
2719867a86 | ||
|
|
0240412ad2 | ||
|
|
7c065c1205 | ||
|
|
f9aa1ad1f2 | ||
|
|
5feffdf544 | ||
|
|
4e56b8bb78 | ||
|
|
845017313c | ||
|
|
dc2830d94f | ||
|
|
552edf8698 | ||
|
|
41c51646fe | ||
|
|
a42024bdbc | ||
|
|
20cfb26a7f | ||
|
|
3972d11827 | ||
|
|
5cc88a0075 | ||
|
|
fc08711111 | ||
|
|
b20c2babec | ||
|
|
cb0facc6ef | ||
|
|
78abb2edcb | ||
|
|
7d350d9def | ||
|
|
48d7daf2c4 | ||
|
|
2782059d88 | ||
|
|
0ca10bc2ac | ||
|
|
880abe2305 | ||
|
|
22f61d6225 | ||
|
|
4fbaa425fb | ||
|
|
e81e228f03 | ||
|
|
1076f89954 | ||
|
|
9c6f977202 | ||
|
|
bd23ba6077 | ||
|
|
c7af56d0ed | ||
|
|
8da6db9fcc | ||
|
|
2fe7342fd7 | ||
|
|
f6221144a8 | ||
|
|
872d713e50 | ||
|
|
d5b04f572b | ||
|
|
0f7a5f1c08 | ||
|
|
a163c565a8 | ||
|
|
413a316b15 | ||
|
|
65a92a49b5 | ||
|
|
563507ca21 | ||
|
|
21b2d02f0a | ||
|
|
19e1a00fd7 | ||
|
|
a02a6a22d0 | ||
|
|
3488421f67 | ||
|
|
34a961088c | ||
|
|
b35509150a | ||
|
|
d096aa2065 | ||
|
|
efd5bef102 | ||
|
|
b8c6e44ab6 | ||
|
|
9a91cc43e2 | ||
|
|
f4cbab52a7 | ||
|
|
57b58cf203 | ||
|
|
9ba8ae08a1 | ||
|
|
dfe81f510e | ||
|
|
f3a0b35442 | ||
|
|
64e3be3bc7 | ||
|
|
4c82d1c56e | ||
|
|
d8451fc2f5 | ||
|
|
8078423252 | ||
|
|
68176b5695 | ||
|
|
1bf7833959 | ||
|
|
89770b922d | ||
|
|
716947bbb1 | ||
|
|
47e0d7786b | ||
|
|
55f9c40bba | ||
|
|
51afa30732 | ||
|
|
23c07316ee | ||
|
|
e740f52e5e | ||
|
|
a731109747 | ||
|
|
a50a011eb3 | ||
|
|
e22c6d3a94 | ||
|
|
50fb9c1795 | ||
|
|
22575c9a01 | ||
|
|
2934922cb5 | ||
|
|
9042ff46c7 | ||
|
|
a1a91539c2 | ||
|
|
468f4f94a3 | ||
|
|
3ebd35437e | ||
|
|
a166bbadad | ||
|
|
7ff07a132a | ||
|
|
6f297bcbb8 | ||
|
|
1c023e15af | ||
|
|
37f96848a7 | ||
|
|
3d04765f51 | ||
|
|
e1152fa549 | ||
|
|
ab47896f17 | ||
|
|
4f13565e51 | ||
|
|
7ab93a59e2 | ||
|
|
943c0d022b | ||
|
|
bea8922c39 | ||
|
|
97c96a7ee1 | ||
|
|
3d831ba7e8 | ||
|
|
df749a98cb | ||
|
|
22bbc9c621 | ||
|
|
30def4e515 | ||
|
|
cf8be37310 | ||
|
|
12409df446 | ||
|
|
3452a08de3 | ||
|
|
425ea0579e | ||
|
|
22afb769af | ||
|
|
884eae269e | ||
|
|
59a973970e | ||
|
|
225383464a | ||
|
|
3d82731325 | ||
|
|
dacdf08309 | ||
|
|
ad281adc97 | ||
|
|
80741c7773 | ||
|
|
532f7a4b17 | ||
|
|
5e87d582e4 | ||
|
|
b9bf47aaca | ||
|
|
0dba882817 | ||
|
|
c419883814 | ||
|
|
6f0ccbf2b5 | ||
|
|
54332c0bd1 | ||
|
|
5f80674e89 | ||
|
|
c4d0d8ff06 | ||
|
|
8ac1b7082a | ||
|
|
f146ae8be4 | ||
|
|
e7728fdc94 | ||
|
|
052122e4d0 | ||
|
|
38827d2b3d | ||
|
|
9e1f16be27 | ||
|
|
c845846317 | ||
|
|
9276556f19 | ||
|
|
c796d18948 | ||
|
|
8dee5520cf | ||
|
|
440e13714e | ||
|
|
44a70b372d | ||
|
|
504286e96e | ||
|
|
ffdd54d2fa | ||
|
|
32804b81c0 | ||
|
|
403b22ade0 | ||
|
|
a4e74abcca | ||
|
|
8dcef5bac0 | ||
|
|
49878bc4e3 | ||
|
|
3f1a71c8a4 | ||
|
|
bf9b2c0da3 | ||
|
|
909a274709 | ||
|
|
fc529b8083 | ||
|
|
f1386f26fb | ||
|
|
cccd09d329 | ||
|
|
0fccf7effe | ||
|
|
4b91a47c8b | ||
|
|
bd40499bbe | ||
|
|
c7c8cd76c6 | ||
|
|
0bb9f0ce41 | ||
|
|
7136afce8e | ||
|
|
ec17c1de6a | ||
|
|
8d6daef354 | ||
|
|
3a09d2de4a | ||
|
|
c78e10f92e | ||
|
|
b113ff35ac | ||
|
|
6360024d20 | ||
|
|
a7683f6bd7 | ||
|
|
e46a9f3f2a | ||
|
|
a8d711d4c8 | ||
|
|
df74fc67bd | ||
|
|
450261abbf | ||
|
|
12230edc54 | ||
|
|
d1cfcf561b | ||
|
|
d143f5af8b | ||
|
|
0f7ae3cda7 | ||
|
|
baf94e56c8 | ||
|
|
905bd1a4c9 | ||
|
|
96bcf24047 | ||
|
|
dfe47235cf | ||
|
|
b82ea8eaa8 | ||
|
|
b1b830c268 | ||
|
|
e654d4a6df | ||
|
|
ac30b17ecb | ||
|
|
95efdb3a51 | ||
|
|
49c165e203 | ||
|
|
a4be351d9f | ||
|
|
3d0401aecd | ||
|
|
7c27572a53 | ||
|
|
1e7760012e | ||
|
|
24d464b6e5 | ||
|
|
499d91f9f8 | ||
|
|
8e0ceaa06b | ||
|
|
4e62641f7e | ||
|
|
688644f5a4 | ||
|
|
4703f2d1f5 | ||
|
|
14149ae949 | ||
|
|
a0fb0d170c | ||
|
|
e133afec86 | ||
|
|
3ae8ee8ddb | ||
|
|
012643a231 | ||
|
|
dccb43f4dc | ||
|
|
15b3bc6a63 | ||
|
|
2d15bef76d | ||
|
|
756d298f04 | ||
|
|
9f35eb1a85 | ||
|
|
c905bb4b6c | ||
|
|
c78af01c8f | ||
|
|
084855645a | ||
|
|
afce9ece89 | ||
|
|
154e50e36d | ||
|
|
80a129102b | ||
|
|
93672a074e | ||
|
|
c7f6f6233c | ||
|
|
68915a9daf | ||
|
|
13eb91f8dd | ||
|
|
1a8355e6fb | ||
|
|
aa2b7ae60a | ||
|
|
acd36b7ea5 | ||
|
|
87245ab79f | ||
|
|
13b6a17827 | ||
|
|
615e4cf24e | ||
|
|
0e6d08f027 | ||
|
|
d593e584dd | ||
|
|
e046b97160 | ||
|
|
567d3dac55 | ||
|
|
a67a0aa924 | ||
|
|
1b1e3e88fe | ||
|
|
ec99636ef0 | ||
|
|
9d955d252a | ||
|
|
f136f6837a | ||
|
|
6fc1fb0966 | ||
|
|
fad203a66d | ||
|
|
c1bab63ebd | ||
|
|
40f012b03c | ||
|
|
a380059389 | ||
|
|
24b998ba2d | ||
|
|
9a1bb09c9f | ||
|
|
3ad66f8937 | ||
|
|
a6f3e7df55 | ||
|
|
9345d3be31 | ||
|
|
8e85bf8839 | ||
|
|
1012dcd194 | ||
|
|
70251ea11e | ||
|
|
9381471fbd | ||
|
|
1c4b716f1a | ||
|
|
c8b0584127 | ||
|
|
5194a361f4 | ||
|
|
c44e5d2a87 | ||
|
|
ee4d514b66 | ||
|
|
863995cb50 | ||
|
|
cbfe72a76e | ||
|
|
4f17d3519c | ||
|
|
3cfcad76ac | ||
|
|
1ca6535811 | ||
|
|
53612ad2e4 | ||
|
|
4b799d264c | ||
|
|
ca5594703a | ||
|
|
7fc2d9dcca | ||
|
|
c413fc1e30 | ||
|
|
b5086c7759 | ||
|
|
92a015ca4d | ||
|
|
3b2802e36d | ||
|
|
7bf23eaa15 | ||
|
|
9afd1c5ee8 | ||
|
|
5e36377b36 | ||
|
|
c988df13a8 | ||
|
|
29a40d31b7 | ||
|
|
ddc27e818b | ||
|
|
3fa70ac841 | ||
|
|
b2b7dfaf37 | ||
|
|
c309c2cf13 | ||
|
|
71304b114a | ||
|
|
0ffcbdbd38 | ||
|
|
e368a17420 | ||
|
|
2fcfb2f67d | ||
|
|
f68a85056e | ||
|
|
943f47d29d | ||
|
|
fd37a2c466 | ||
|
|
eacdd7afe8 | ||
|
|
fe5ea52cdf | ||
|
|
ca6d77cbb3 | ||
|
|
1145941d11 | ||
|
|
d61697a152 | ||
|
|
38b77a9c79 | ||
|
|
7d294ee8c2 | ||
|
|
33d9422d03 | ||
|
|
bb7302c23a | ||
|
|
d50ae63a5a | ||
|
|
1961836e19 | ||
|
|
f2ed7c15ce | ||
|
|
4dce173630 | ||
|
|
86f868b2d4 | ||
|
|
363064f5c0 | ||
|
|
9d99ee9cfc | ||
|
|
db8969707d | ||
|
|
a24ac37dfd | ||
|
|
1b04d471b3 | ||
|
|
9cc400a081 | ||
|
|
e233aeec0c | ||
|
|
5dfd621900 | ||
|
|
f0f6a9988f | ||
|
|
587438938c | ||
|
|
2497ac68d1 | ||
|
|
75918c59cc | ||
|
|
8b38a20c18 | ||
|
|
e7b76bfdc5 | ||
|
|
3503ff6d36 | ||
|
|
192e21a9fc | ||
|
|
24e288d584 | ||
|
|
0e5ffda5e5 | ||
|
|
cdf6f18ec0 | ||
|
|
188245fa7f | ||
|
|
e10b747d6a | ||
|
|
f2bb6a05a5 | ||
|
|
f41da19db5 | ||
|
|
d0a56dbb21 | ||
|
|
acbf286e59 | ||
|
|
0f7c160409 | ||
|
|
5113aacb89 | ||
|
|
4e31636181 | ||
|
|
1e497d2c44 | ||
|
|
70bd4fa161 | ||
|
|
65996050d5 | ||
|
|
7f52031199 | ||
|
|
5430f3d33c | ||
|
|
43075faaf8 | ||
|
|
f3a1272e31 | ||
|
|
41c028d4d9 | ||
|
|
a17ce04552 | ||
|
|
d0b4652dcd | ||
|
|
e66f71c76e | ||
|
|
6effd4b846 | ||
|
|
df861f5403 | ||
|
|
e74346fed6 | ||
|
|
6961c467a6 | ||
|
|
892d305165 | ||
|
|
fa16261d7a | ||
|
|
15991fd2f7 | ||
|
|
c80b8f60f8 | ||
|
|
ab6253cbd0 | ||
|
|
35ba267115 | ||
|
|
ab24e6e1c1 | ||
|
|
e25ae27a15 | ||
|
|
2b7c524908 | ||
|
|
0b069df9ce | ||
|
|
60c9ba88ae | ||
|
|
cc2e60c84a | ||
|
|
83c2c4e92e | ||
|
|
ab3d9e82ef | ||
|
|
b6063dd534 | ||
|
|
e6754354e4 | ||
|
|
4849619d67 | ||
|
|
9b0ace242a | ||
|
|
e94ba74058 | ||
|
|
569fa06d2d | ||
|
|
46dce17abc | ||
|
|
40d8f4a352 | ||
|
|
6415785220 | ||
|
|
7735edeae8 | ||
|
|
0f81d1dbb3 | ||
|
|
ae1ec8b558 | ||
|
|
09c2b39530 | ||
|
|
b443e866f9 | ||
|
|
d4404713a8 | ||
|
|
47409a9a99 | ||
|
|
60bfea2d3b | ||
|
|
d3ed8eaed5 | ||
|
|
692dccf110 | ||
|
|
92caf98683 | ||
|
|
6178d38895 | ||
|
|
40fb38a9ba | ||
|
|
20e68d53fd | ||
|
|
2d3557e049 | ||
|
|
d8f4bc7395 | ||
|
|
353f9bb809 | ||
|
|
ccfe3ad4f7 | ||
|
|
9012820c03 | ||
|
|
fe2af19e42 | ||
|
|
f721e053f1 | ||
|
|
e6ad9feb84 | ||
|
|
635350c40e | ||
|
|
17edd33703 | ||
|
|
b0f2a871c6 | ||
|
|
8928a8a1dc | ||
|
|
2b6f37a6cc | ||
|
|
f3a3b87861 | ||
|
|
9cf6ee78d4 | ||
|
|
bbc2f3962f | ||
|
|
be49eb22d2 | ||
|
|
fb47067215 | ||
|
|
2c80ef178d | ||
|
|
9af8112148 | ||
|
|
57c36f437a | ||
|
|
5ed8a34566 | ||
|
|
ea8df9bd61 | ||
|
|
b0c51e03b7 | ||
|
|
336924ef23 | ||
|
|
ad28ca4a90 | ||
|
|
aebbe86cfc | ||
|
|
df9faf4943 | ||
|
|
3e295b6be4 | ||
|
|
8dd6dbf995 | ||
|
|
612139f2ff | ||
|
|
240bcabb76 | ||
|
|
cda27d5963 | ||
|
|
2f8c3997f7 | ||
|
|
46b89a48db | ||
|
|
5c9cbee2f9 | ||
|
|
ee8973c239 | ||
|
|
2e2813f363 | ||
|
|
7ceca0769f | ||
|
|
4d277cc61f | ||
|
|
e67fbb4621 | ||
|
|
29b5357ceb | ||
|
|
9dabec107b | ||
|
|
f2a2ad90b7 | ||
|
|
cfe4c0c510 | ||
|
|
23cd51a6da | ||
|
|
7396395f90 | ||
|
|
a1819bf232 | ||
|
|
8accf07d46 | ||
|
|
6dcbace572 | ||
|
|
e90c86ec2f | ||
|
|
971ae1fa4d | ||
|
|
4abe87036c | ||
|
|
8d1b44db97 | ||
|
|
b537f9925b | ||
|
|
f2fe8eaf86 | ||
|
|
46715cac08 | ||
|
|
0f21eba57f | ||
|
|
cb7620395a | ||
|
|
3a40af8871 | ||
|
|
c9b5074bc4 | ||
|
|
44d4d0d767 | ||
|
|
64af13f40d | ||
|
|
e9b59c6bef | ||
|
|
3d03659508 | ||
|
|
0374d2de48 | ||
|
|
2627dc5ee4 | ||
|
|
5554332b5b | ||
|
|
1cffea892b | ||
|
|
fd859815b0 | ||
|
|
166e26d101 | ||
|
|
be081eec3f | ||
|
|
55b00a87f6 | ||
|
|
429b26cee8 | ||
|
|
fafe6b0ff7 | ||
|
|
5b156006fb | ||
|
|
75f0c08ca4 | ||
|
|
1f4325e7db | ||
|
|
f2e7b40425 | ||
|
|
4ee3086b6d | ||
|
|
a3a715c3ba | ||
|
|
6cad4a3c33 | ||
|
|
b9b6f4fd44 | ||
|
|
17d1994a53 | ||
|
|
13184e72e1 | ||
|
|
911e8d21a7 | ||
|
|
5b69a2925f | ||
|
|
d1c900a620 | ||
|
|
6bfeb54f3c | ||
|
|
198fede915 | ||
|
|
1212ae3eb3 | ||
|
|
1266dcc0c7 | ||
|
|
6fcddf4a47 | ||
|
|
dfea424b94 | ||
|
|
9d03435aa1 | ||
|
|
26c20a7a22 | ||
|
|
470da06ecf | ||
|
|
a746a310bc | ||
|
|
3dbb516084 | ||
|
|
32177283b3 | ||
|
|
3a66e90b7a | ||
|
|
a454fb10ec | ||
|
|
b5386a35ee | ||
|
|
11651da411 | ||
|
|
88d52c44ad | ||
|
|
2d7d4bbd4e | ||
|
|
e6ee278fde | ||
|
|
6380cf9ed0 | ||
|
|
2e78dc52c7 | ||
|
|
ccb42d3249 | ||
|
|
c5009ab44b | ||
|
|
9d15cd43a3 | ||
|
|
0780e10fa2 | ||
|
|
0731f63237 | ||
|
|
a29896042b | ||
|
|
68ebc08c9d | ||
|
|
a1df526f93 | ||
|
|
0023ecefa4 | ||
|
|
511f156603 | ||
|
|
3f223b1ba0 | ||
|
|
a1528a1a63 | ||
|
|
b8bfddbf3a | ||
|
|
47fc813027 | ||
|
|
c7f2228a44 | ||
|
|
b0e0f045f8 | ||
|
|
1296514794 | ||
|
|
18e797095f | ||
|
|
85aa2ad4e6 | ||
|
|
818f6dc045 | ||
|
|
1c162c6390 | ||
|
|
def3a28fb5 | ||
|
|
d1378a0236 | ||
|
|
e544c7a65a | ||
|
|
24f48f668c | ||
|
|
9988a090ac | ||
|
|
d36e145d06 | ||
|
|
498d63ea00 | ||
|
|
7dc620a3ba | ||
|
|
66145e1d23 | ||
|
|
7bf8621afe | ||
|
|
ce3f74232e | ||
|
|
5b92d4b88c | ||
|
|
4daf6ba057 | ||
|
|
955e9899af | ||
|
|
fa3d0887ef | ||
|
|
5d5c6cf71c | ||
|
|
89aac45f41 | ||
|
|
4965fd5f4c | ||
|
|
87fbb8ec98 | ||
|
|
0d92d4ba61 | ||
|
|
b0df93bbcb | ||
|
|
290d0b226a | ||
|
|
8b3469610c | ||
|
|
50b47fb73b | ||
|
|
5334cb8688 | ||
|
|
38983df42d | ||
|
|
df963cb71c | ||
|
|
e9368fb04e | ||
|
|
e2a1630cf4 | ||
|
|
4f15b7c9fa | ||
|
|
63f500ad7f | ||
|
|
a9fb4546e1 | ||
|
|
cabbbf7f02 | ||
|
|
59324b0082 | ||
|
|
6a356c82a5 | ||
|
|
70f0f5714a | ||
|
|
07b527a0f2 | ||
|
|
80aa75aab1 | ||
|
|
0cf4211aa5 | ||
|
|
1de02a5099 | ||
|
|
bb1cecb95b | ||
|
|
d82397a173 | ||
|
|
856cf5e568 | ||
|
|
9f5a6ee549 | ||
|
|
9f3f644b83 | ||
|
|
a2f0837d14 | ||
|
|
c7f6889534 | ||
|
|
0415326d09 | ||
|
|
16a0f8ece0 | ||
|
|
5d1ef296b3 | ||
|
|
16dbcde90b | ||
|
|
50cbf25c72 | ||
|
|
7b87de2b4c | ||
|
|
1ce54a7925 | ||
|
|
1bfe7dd99b | ||
|
|
27e855ddbd | ||
|
|
3d1bed0f8f | ||
|
|
5c9ea9b63a | ||
|
|
7c034f5670 | ||
|
|
3b9f5a417a | ||
|
|
cde501af8d | ||
|
|
3c5592c1c8 | ||
|
|
2508e022bb | ||
|
|
01fcbc24e8 | ||
|
|
204e639679 | ||
|
|
3d301ec730 | ||
|
|
9ab6d57019 | ||
|
|
37c473130f | ||
|
|
5f95987a48 | ||
|
|
d530b34073 | ||
|
|
35dec7a5ec | ||
|
|
baedad8124 | ||
|
|
007378c3a6 | ||
|
|
beae9fd6ec | ||
|
|
b7507076c6 | ||
|
|
6b5ade3ca0 | ||
|
|
715192d26c | ||
|
|
ce140460af | ||
|
|
d30b0403ce | ||
|
|
255c993548 | ||
|
|
557ae4165c | ||
|
|
a31395ed80 | ||
|
|
397886d289 | ||
|
|
7307bec2ae | ||
|
|
0cd5147e1a | ||
|
|
36d5b092d7 | ||
|
|
f9014dbab3 | ||
|
|
755d5f77ea | ||
|
|
906d9af7b7 | ||
|
|
14dcb37ee1 | ||
|
|
c1c2a27358 | ||
|
|
5ab9657f9c | ||
|
|
7a78f9f5aa | ||
|
|
ac8c65f062 | ||
|
|
1954a9f3f8 | ||
|
|
3b764f9c90 | ||
|
|
10f55cc549 | ||
|
|
cd8d955646 | ||
|
|
bba07c9080 | ||
|
|
dba84a33b9 | ||
|
|
ae49166aa2 | ||
|
|
e09185fd0e | ||
|
|
56379bb3b9 | ||
|
|
027e4b4f25 | ||
|
|
ba951cb6e3 | ||
|
|
ae85cf4b6c | ||
|
|
dbc79f8c42 | ||
|
|
54c3070607 |
19
.github/release-drafter.yml
vendored
Normal file
19
.github/release-drafter.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
name-template: 'v$NEXT_PATCH_VERSION 🌈'
|
||||||
|
tag-template: 'v$NEXT_PATCH_VERSION'
|
||||||
|
categories:
|
||||||
|
- title: '🚀 Features'
|
||||||
|
labels:
|
||||||
|
- 'feature'
|
||||||
|
- 'enhancement'
|
||||||
|
- title: '🐛 Bug Fixes'
|
||||||
|
labels:
|
||||||
|
- 'fix'
|
||||||
|
- 'bugfix'
|
||||||
|
- 'bug'
|
||||||
|
- title: '🧰 Maintenance'
|
||||||
|
label: 'chore'
|
||||||
|
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||||
|
template: |
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
$CHANGES
|
||||||
22
.github/workflows/maven-build.yml
vendored
Normal file
22
.github/workflows/maven-build.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
name: Java CI Build and Test
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
java: [ '1.8.0', '11.0.x', '13.0.x' ]
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Set up JDK
|
||||||
|
uses: actions/setup-java@v1
|
||||||
|
with:
|
||||||
|
java-version: ${{ matrix.java }}
|
||||||
|
- name: Maven Download all dependencies
|
||||||
|
run: mvn -B org.apache.maven.plugins:maven-dependency-plugin:3.1.1:go-offline
|
||||||
|
- name: Maven Build
|
||||||
|
run: mvn -B install site --file pom.xml
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -3,3 +3,7 @@ target
|
|||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
*.iws
|
*.iws
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.settings/
|
||||||
|
.DS_Store
|
||||||
|
|||||||
76
CODE_OF_CONDUCT.md
Normal file
76
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as
|
||||||
|
contributors and maintainers pledge to making participation in our project and
|
||||||
|
our community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||||
|
level of experience, education, socio-economic status, nationality, personal
|
||||||
|
appearance, race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment
|
||||||
|
include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
|
advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic
|
||||||
|
address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable
|
||||||
|
behavior and are expected to take appropriate and fair corrective action in
|
||||||
|
response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or
|
||||||
|
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||||
|
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||||
|
permanently any contributor for other behaviors that they deem inappropriate,
|
||||||
|
threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces
|
||||||
|
when an individual is representing the project or its community. Examples of
|
||||||
|
representing a project or community include using an official project e-mail
|
||||||
|
address, posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event. Representation of a project may be
|
||||||
|
further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported by contacting the project team at bitwiseman@gmail.com. All
|
||||||
|
complaints will be reviewed and investigated and will result in a response that
|
||||||
|
is deemed necessary and appropriate to the circumstances. The project team is
|
||||||
|
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||||
|
Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||||
|
faith may face temporary or permanent repercussions as determined by other
|
||||||
|
members of the project's leadership.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||||
|
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see
|
||||||
|
https://www.contributor-covenant.org/faq
|
||||||
62
CONTRIBUTING.md
Normal file
62
CONTRIBUTING.md
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
## Using WireMock and Snapshots
|
||||||
|
|
||||||
|
This project has started converting to using WireMock to stub out http responses instead of use live data.
|
||||||
|
This change will allow tests to run in a CI environment without needing to touch github.com.
|
||||||
|
The tests will instead serve previously recorded responses from local data files.
|
||||||
|
|
||||||
|
### Running WireMock tests
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
`mvn install -Dtest=WireMockStatusReporterTest`
|
||||||
|
|
||||||
|
This the default behavior.
|
||||||
|
|
||||||
|
|
||||||
|
### Setting up credential
|
||||||
|
|
||||||
|
1. Create an OAuth token on github.com
|
||||||
|
2. Set the GITHUB_OAUTH environment variable to the value of that token
|
||||||
|
3. Set the system property `test.github.useProxy` (usually like "-Dtest.github.useProxy" as a Java VM option)
|
||||||
|
|
||||||
|
`mvn install -Dtest.github.useProxy -Dtest=WireMockStatusReporterTest`
|
||||||
|
|
||||||
|
4. The above should report no test failures and include the following console output:
|
||||||
|
|
||||||
|
`WireMockStatusReporterTest: GitHub proxying and user auth correctly configured for user login: <your login>`
|
||||||
|
|
||||||
|
Whenever you run tests with `-Dtest.github.useProxy`, they will try to get data from local files but will fallback to proxying to github if not found.
|
||||||
|
|
||||||
|
|
||||||
|
### Writing a new test
|
||||||
|
|
||||||
|
Once you have credentials setup, you add new test classes and test methods as you would normally.
|
||||||
|
Keep `useProxy` enabled and iterate on your tests as needed. Remember, while proxying your tests are interacting with GitHub - you will need to clean up your state between runs.
|
||||||
|
|
||||||
|
When you are ready to create a snapshot of your test data,
|
||||||
|
run your test with `test.github.takeSnapshot` ("-Dtest.github.takeSnapshot" as a Java VM option). For example:
|
||||||
|
|
||||||
|
`mvn install -Dtest.github.takeSnapshot -Dtest=YourTestClassName`
|
||||||
|
|
||||||
|
The above command would create snapshot WireMock data files under the path `src/test/resources/org/kohsuhke/github/YourTestClassName/wiremock`.
|
||||||
|
Each method would get a separate director that would hold the data files for that test method.
|
||||||
|
|
||||||
|
Add all files including the generated data to your commit and submit a PR.
|
||||||
|
|
||||||
|
### Modifying existing tests
|
||||||
|
|
||||||
|
When modifying existing tests, you can change the stubbed WireMock data files by hand or you can try generating a new snapshot.
|
||||||
|
|
||||||
|
#### Manual editing of data (minor changes only)
|
||||||
|
|
||||||
|
If you know what data will change, it is sometimes simplest to make any required changes to the data files manually.
|
||||||
|
This can be easier if the changes are minor or when you development environment is not setup to to take updated snapshots.
|
||||||
|
|
||||||
|
#### Generating a new snapshot
|
||||||
|
|
||||||
|
For more most changes, it is recommended to take a new snapshot when updating tests.
|
||||||
|
Delete the wiremock data files for the test method you will be modifying.
|
||||||
|
For more significant changes, you can even delete the WireMock files for an entire test class.
|
||||||
|
Then follow the same as when writing a new test: run with proxy enabled to debug, take a new snapshot when done, commit everything, and submit the PR.
|
||||||
3
README
3
README
@@ -1,3 +0,0 @@
|
|||||||
Java API for GitHub
|
|
||||||
|
|
||||||
See http://github-api.kohsuke.org/ for more details
|
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
Java API for GitHub
|
||||||
|
|
||||||
|
See https://github-api.kohsuke.org/ for more details
|
||||||
405
pom.xml
405
pom.xml
@@ -3,63 +3,200 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.kohsuke</groupId>
|
<groupId>org.kohsuke</groupId>
|
||||||
<artifactId>pom</artifactId>
|
<artifactId>pom</artifactId>
|
||||||
<version>14</version>
|
<version>21</version>
|
||||||
|
<relativePath />
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>github-api</artifactId>
|
<artifactId>github-api</artifactId>
|
||||||
<version>1.73</version>
|
<version>1.99</version>
|
||||||
<name>GitHub API for Java</name>
|
<name>GitHub API for Java</name>
|
||||||
<url>http://github-api.kohsuke.org/</url>
|
<url>https://github-api.kohsuke.org/</url>
|
||||||
<description>GitHub API for Java</description>
|
<description>GitHub API for Java</description>
|
||||||
|
|
||||||
<scm>
|
<scm>
|
||||||
<connection>scm:git:git@github.com/kohsuke/${project.artifactId}.git</connection>
|
<connection>scm:git:git@github.com/github-api/${project.artifactId}.git</connection>
|
||||||
<developerConnection>scm:git:ssh://git@github.com/kohsuke/${project.artifactId}.git</developerConnection>
|
<developerConnection>scm:git:ssh://git@github.com/github-api/${project.artifactId}.git</developerConnection>
|
||||||
<url>http://${project.artifactId}.kohsuke.org/</url>
|
<url>https://${project.artifactId}.kohsuke.org/</url>
|
||||||
<tag>github-api-1.73</tag>
|
<tag>github-api-1.99</tag>
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
<site>
|
<site>
|
||||||
<id>github-pages</id>
|
<id>github-pages</id>
|
||||||
<url>gitsite:git@github.com/kohsuke/${project.artifactId}.git</url>
|
<url>gitsite:git@github.com/github-api/${project.artifactId}.git</url>
|
||||||
</site>
|
</site>
|
||||||
</distributionManagement>
|
</distributionManagement>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<findbugs-maven-plugin.version>3.0.2</findbugs-maven-plugin.version>
|
<spotbugs-maven-plugin.version>3.1.12.2</spotbugs-maven-plugin.version>
|
||||||
<findbugs-maven-plugin.failOnError>true</findbugs-maven-plugin.failOnError>
|
<spotbugs.version>3.1.12</spotbugs.version>
|
||||||
|
<spotbugs-maven-plugin.failOnError>true</spotbugs-maven-plugin.failOnError>
|
||||||
|
<hamcrest.version>2.2</hamcrest.version>
|
||||||
|
<okhttp3.version>3.12.3</okhttp3.version>
|
||||||
|
<okio.version>2.4.1</okio.version>
|
||||||
|
<jacoco.coverage.target.class>.80</jacoco.coverage.target.class>
|
||||||
|
<jacoco.coverage.target.method>0.20</jacoco.coverage.target.method>
|
||||||
|
<jacoco.coverage.target.line>0.50</jacoco.coverage.target.line>
|
||||||
|
<jacoco.coverage.target.other>0.50</jacoco.coverage.target.other>
|
||||||
|
<!-- For non-ci builds we'd like the build to still complete if jacoco metrics aren't met. -->
|
||||||
|
<jacoco.haltOnFailure>false</jacoco.haltOnFailure>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
<extensions>
|
||||||
|
<extension>
|
||||||
|
<groupId>org.apache.maven.scm</groupId>
|
||||||
|
<artifactId>maven-scm-provider-gitexe</artifactId>
|
||||||
|
<version>1.11.2</version>
|
||||||
|
</extension>
|
||||||
|
<extension>
|
||||||
|
<groupId>org.apache.maven.scm</groupId>
|
||||||
|
<artifactId>maven-scm-manager-plexus</artifactId>
|
||||||
|
<version>1.11.2</version>
|
||||||
|
</extension>
|
||||||
|
</extensions>
|
||||||
|
<testResources>
|
||||||
|
<testResource>
|
||||||
|
<directory>src/test/resources</directory>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/wiremock/**</exclude>
|
||||||
|
</excludes>
|
||||||
|
</testResource>
|
||||||
|
</testResources>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<!-- adds jacoco coverage -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.jacoco</groupId>
|
||||||
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
|
<version>0.8.5</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>3.1.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>8</source>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>com.infradna.tool</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>bridge-method-injector</artifactId>
|
<artifactId>maven-site-plugin</artifactId>
|
||||||
<version>1.14</version>
|
<version>3.8.2</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-release-plugin</artifactId>
|
||||||
|
<version>2.5.3</version>
|
||||||
|
<configuration>
|
||||||
|
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||||
|
<useReleaseProfile>false</useReleaseProfile>
|
||||||
|
<releaseProfiles>release</releaseProfiles>
|
||||||
|
<goals>deploy</goals>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||||
|
<version>3.0.0</version>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.bcel</groupId>
|
||||||
|
<artifactId>bcel</artifactId>
|
||||||
|
<version>6.4.1</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.8</source>
|
||||||
|
<target>1.8</target>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<annotationProcessorPath>
|
||||||
|
<groupId>org.jenkins-ci</groupId>
|
||||||
|
<artifactId>annotation-indexer</artifactId>
|
||||||
|
<version>1.12</version>
|
||||||
|
</annotationProcessorPath>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.22.2</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>animal-sniffer-maven-plugin</artifactId>
|
||||||
|
<version>1.18</version>
|
||||||
|
<configuration>
|
||||||
|
<signature>
|
||||||
|
<groupId>org.codehaus.mojo.signature</groupId>
|
||||||
|
<artifactId>java18</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
</signature>
|
||||||
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
|
<id>ensure-java-1.8-class-library</id>
|
||||||
|
<phase>test</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>process</goal>
|
<goal>check</goal>
|
||||||
</goals>
|
</goals>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.infradna.tool</groupId>
|
||||||
|
<artifactId>bridge-method-injector</artifactId>
|
||||||
|
<version>1.18</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>process</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>com.github.spotbugs</groupId>
|
||||||
<artifactId>findbugs-maven-plugin</artifactId>
|
<artifactId>spotbugs-maven-plugin</artifactId>
|
||||||
<version>${findbugs-maven-plugin.version}</version>
|
<version>${spotbugs-maven-plugin.version}</version>
|
||||||
<configuration>
|
<configuration>
|
||||||
<xmlOutput>true</xmlOutput>
|
<xmlOutput>true</xmlOutput>
|
||||||
<failOnError>${findbugs-maven-plugin.failOnError}</failOnError>
|
<failOnError>${spotbugs-maven-plugin.failOnError}</failOnError>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>run-findbugs</id>
|
<id>run-spotbugs</id>
|
||||||
<phase>verify</phase>
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>check</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<dependencies>
|
||||||
|
<!-- overwrite dependency on spotbugs if you want to specify the version of spotbugs -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.spotbugs</groupId>
|
||||||
|
<artifactId>spotbugs</artifactId>
|
||||||
|
<version>${spotbugs.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</plugin>
|
||||||
|
<!-- Do not use gmaven plugin -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.gmaven</groupId>
|
||||||
|
<artifactId>gmaven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>check</goal>
|
|
||||||
</goals>
|
</goals>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
@@ -69,35 +206,55 @@
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-lang</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
<version>2.6</version>
|
<version>3.9</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-codec</groupId>
|
<groupId>commons-codec</groupId>
|
||||||
<artifactId>commons-codec</artifactId>
|
<artifactId>commons-codec</artifactId>
|
||||||
<version>1.7</version>
|
<version>1.13</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest</artifactId>
|
||||||
|
<version>${hamcrest.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- This is needed in order to force junit4 and JTH tests to use newer hamcrest version -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-core</artifactId>
|
||||||
|
<version>${hamcrest.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hamcrest</groupId>
|
||||||
|
<artifactId>hamcrest-library</artifactId>
|
||||||
|
<version>${hamcrest.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
<version>4.11</version>
|
<version>4.12</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
<version>2.2.3</version>
|
<version>2.10.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>commons-io</groupId>
|
<groupId>commons-io</groupId>
|
||||||
<artifactId>commons-io</artifactId>
|
<artifactId>commons-io</artifactId>
|
||||||
<version>1.4</version>
|
<version>2.6</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.infradna.tool</groupId>
|
<groupId>com.infradna.tool</groupId>
|
||||||
<artifactId>bridge-method-annotation</artifactId>
|
<artifactId>bridge-method-annotation</artifactId>
|
||||||
<version>1.14</version>
|
<version>1.18</version>
|
||||||
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.kohsuke.stapler</groupId>
|
<groupId>org.kohsuke.stapler</groupId>
|
||||||
@@ -108,60 +265,224 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jgit</groupId>
|
<groupId>org.eclipse.jgit</groupId>
|
||||||
<artifactId>org.eclipse.jgit</artifactId>
|
<artifactId>org.eclipse.jgit</artifactId>
|
||||||
<version>3.1.0.201310021548-r</version>
|
<version>5.5.1.201910021850-r</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okio</groupId>
|
||||||
|
<artifactId>okio</artifactId>
|
||||||
|
<version>${okio.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>${okhttp3.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
|
<artifactId>okhttp-urlconnection</artifactId>
|
||||||
|
<version>${okhttp3.version}</version>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.squareup.okhttp</groupId>
|
<groupId>com.squareup.okhttp</groupId>
|
||||||
<artifactId>okhttp-urlconnection</artifactId>
|
<artifactId>okhttp-urlconnection</artifactId>
|
||||||
<version>2.0.0</version>
|
<version>2.7.5</version>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.kohsuke</groupId>
|
<groupId>org.kohsuke</groupId>
|
||||||
<artifactId>wordnet-random-name</artifactId>
|
<artifactId>wordnet-random-name</artifactId>
|
||||||
<version>1.2</version>
|
<version>1.3</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>mockito-all</artifactId>
|
<artifactId>mockito-core</artifactId>
|
||||||
<version>1.9.5</version>
|
<version>3.1.0</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.code.findbugs</groupId>
|
<groupId>com.github.spotbugs</groupId>
|
||||||
<artifactId>annotations</artifactId>
|
<artifactId>spotbugs-annotations</artifactId>
|
||||||
<version>3.0.0</version>
|
<version>${spotbugs.version}</version>
|
||||||
<scope>provided</scope>
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.tomakehurst</groupId>
|
||||||
|
<artifactId>wiremock-jre8-standalone</artifactId>
|
||||||
|
<version>2.25.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>2.8.6</version>
|
||||||
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<repositories>
|
<repositories>
|
||||||
<repository>
|
<repository>
|
||||||
<id>repo.jenkins-ci.org</id>
|
<id>repo.jenkins-ci.org</id>
|
||||||
<url>http://repo.jenkins-ci.org/public/</url>
|
<url>https://repo.jenkins-ci.org/public/</url>
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
<pluginRepositories>
|
<pluginRepositories>
|
||||||
<pluginRepository>
|
<pluginRepository>
|
||||||
<id>repo.jenkins-ci.org</id>
|
<id>repo.jenkins-ci.org</id>
|
||||||
<url>http://repo.jenkins-ci.org/public/</url>
|
<url>https://repo.jenkins-ci.org/public/</url>
|
||||||
</pluginRepository>
|
</pluginRepository>
|
||||||
</pluginRepositories>
|
</pluginRepositories>
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>jacoco</id>
|
||||||
|
<activation>
|
||||||
|
<property>
|
||||||
|
<name>enable-jacoco</name>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.jacoco</groupId>
|
||||||
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
|
<version>0.8.5</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>prepare-agent</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<!-- attached to Maven test phase -->
|
||||||
|
<execution>
|
||||||
|
<id>report</id>
|
||||||
|
<phase>test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>report</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>check</id>
|
||||||
|
<phase>install</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>check</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<rules>
|
||||||
|
<rule>
|
||||||
|
<!--We end up with chatty logs, but it shows us which particular classes -->
|
||||||
|
<!--are lacking in coverage. If this is too much, just remove the -->
|
||||||
|
<!--<element>CLASS</element> tag below. -->
|
||||||
|
<element>CLASS</element>
|
||||||
|
<limits>
|
||||||
|
<!-- These limits can be overridden, in the form of `0.50` for -->
|
||||||
|
<!-- 50%, as necessary. Using a property just puts it in one spot. -->
|
||||||
|
<!--
|
||||||
|
<limit>
|
||||||
|
<counter>LINE</counter>
|
||||||
|
<value>COVEREDRATIO</value>
|
||||||
|
<minimum>${jacoco.coverage.target.lines}</minimum>
|
||||||
|
</limit>
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
<limit>
|
||||||
|
<counter>BRANCH</counter>
|
||||||
|
<value>COVEREDRATIO</value>
|
||||||
|
<minimum>${jacoco.coverage.target.other}</minimum>
|
||||||
|
</limit>
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
<limit>
|
||||||
|
<counter>INSTRUCTION</counter>
|
||||||
|
<value>COVEREDRATIO</value>
|
||||||
|
<minimum>${jacoco.coverage.target.other}</minimum>
|
||||||
|
</limit>
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
<limit>
|
||||||
|
<counter>COMPLEXITY</counter>
|
||||||
|
<value>COVEREDRATIO</value>
|
||||||
|
<minimum>${jacoco.coverage.target.other}</minimum>
|
||||||
|
</limit>
|
||||||
|
-->
|
||||||
|
<limit>
|
||||||
|
<counter>METHOD</counter>
|
||||||
|
<value>COVEREDRATIO</value>
|
||||||
|
<minimum>${jacoco.coverage.target.method}</minimum>
|
||||||
|
</limit>
|
||||||
|
<!-- <limit>-->
|
||||||
|
<!-- <counter>CLASS</counter>-->
|
||||||
|
<!-- <value>COVEREDRATIO</value>-->
|
||||||
|
<!-- <minimum>${jacoco.coverage.target.class}</minimum>-->
|
||||||
|
<!-- </limit>-->
|
||||||
|
</limits>
|
||||||
|
<excludes>
|
||||||
|
<exclude>org.kohsuke.github.extras.okhttp3.ObsoleteUrlFactory.**</exclude>
|
||||||
|
<exclude>org.kohsuke.github.extras.okhttp3.ObsoleteUrlFactory</exclude>
|
||||||
|
<exclude>org.kohsuke.github.extras.OkHttp3Connector</exclude>
|
||||||
|
<!--<exclude>io.jenkins.plugins.todeclarative.converter.api.*</exclude>-->
|
||||||
|
</excludes>
|
||||||
|
</rule>
|
||||||
|
</rules>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>release</id>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-gpg-plugin</artifactId>
|
||||||
|
<version>1.6</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>sign-artifacts</id>
|
||||||
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>sign</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<gpgArguments>
|
||||||
|
<arg>--pinentry-mode</arg>
|
||||||
|
<arg>loopback</arg>
|
||||||
|
</gpgArguments>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>3.2.0</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
<reporting>
|
<reporting>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-javadoc-plugin</artifactId>
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</reporting>
|
</reporting>
|
||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
<license>
|
<license>
|
||||||
<name>The MIT license</name>
|
<name>The MIT license</name>
|
||||||
<url>http://www.opensource.org/licenses/mit-license.php</url>
|
<url>https://www.opensource.org/licenses/mit-license.php</url>
|
||||||
<distribution>repo</distribution>
|
<distribution>repo</distribution>
|
||||||
</license>
|
</license>
|
||||||
</licenses>
|
</licenses>
|
||||||
|
|||||||
64
src/main/java/org/kohsuke/github/AbuseLimitHandler.java
Normal file
64
src/main/java/org/kohsuke/github/AbuseLimitHandler.java
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InterruptedIOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pluggable strategy to determine what to do when the API abuse limit is hit.
|
||||||
|
*
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
* @see GitHubBuilder#withAbuseLimitHandler(AbuseLimitHandler)
|
||||||
|
* @see <a href="https://developer.github.com/v3/#abuse-rate-limits">documentation</a>
|
||||||
|
* @see RateLimitHandler
|
||||||
|
*/
|
||||||
|
public abstract class AbuseLimitHandler {
|
||||||
|
/**
|
||||||
|
* Called when the library encounters HTTP error indicating that the API abuse limit is reached.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Any exception thrown from this method will cause the request to fail, and the caller of github-api
|
||||||
|
* will receive an exception. If this method returns normally, another request will be attempted.
|
||||||
|
* For that to make sense, the implementation needs to wait for some time.
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/#abuse-rate-limits">API documentation from GitHub</a>
|
||||||
|
* @param e
|
||||||
|
* Exception from Java I/O layer. If you decide to fail the processing, you can throw
|
||||||
|
* this exception (or wrap this exception into another exception and throw it).
|
||||||
|
* @param uc
|
||||||
|
* Connection that resulted in an error. Useful for accessing other response headers.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public abstract void onError(IOException e, HttpURLConnection uc) throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait until the API abuse "wait time" is passed.
|
||||||
|
*/
|
||||||
|
public static final AbuseLimitHandler WAIT = new AbuseLimitHandler() {
|
||||||
|
@Override
|
||||||
|
public void onError(IOException e, HttpURLConnection uc) throws IOException {
|
||||||
|
try {
|
||||||
|
Thread.sleep(parseWaitTime(uc));
|
||||||
|
} catch (InterruptedException ex) {
|
||||||
|
throw (InterruptedIOException)new InterruptedIOException().initCause(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private long parseWaitTime(HttpURLConnection uc) {
|
||||||
|
String v = uc.getHeaderField("Retry-After");
|
||||||
|
if (v==null) return 60 * 1000; // can't tell, return 1 min
|
||||||
|
|
||||||
|
return Math.max(1000, Long.parseLong(v)*1000);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fail immediately.
|
||||||
|
*/
|
||||||
|
public static final AbuseLimitHandler FAIL = new AbuseLimitHandler() {
|
||||||
|
@Override
|
||||||
|
public void onError(IOException e, HttpURLConnection uc) throws IOException {
|
||||||
|
throw (IOException)new IOException("Abuse limit reached").initCause(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
17
src/main/java/org/kohsuke/github/EnforcementLevel.java
Normal file
17
src/main/java/org/kohsuke/github/EnforcementLevel.java
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This was added during preview API period but it has changed since then.
|
||||||
|
*
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public enum EnforcementLevel {
|
||||||
|
OFF, NON_ADMINS, EVERYONE;
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return name().toLowerCase(Locale.ENGLISH);
|
||||||
|
}
|
||||||
|
}
|
||||||
172
src/main/java/org/kohsuke/github/GHApp.java
Normal file
172
src/main/java/org/kohsuke/github/GHApp.java
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.MACHINE_MAN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Github App.
|
||||||
|
*
|
||||||
|
* @author Paulo Miguel Almeida
|
||||||
|
*
|
||||||
|
* @see GitHub#getApp()
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class GHApp extends GHObject {
|
||||||
|
|
||||||
|
private GitHub root;
|
||||||
|
private GHUser owner;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
@JsonProperty("external_url")
|
||||||
|
private String externalUrl;
|
||||||
|
private Map<String,String> permissions;
|
||||||
|
private List<GHEvent> events;
|
||||||
|
@JsonProperty("installations_count")
|
||||||
|
private long installationsCount;
|
||||||
|
@JsonProperty("html_url")
|
||||||
|
private String htmlUrl;
|
||||||
|
|
||||||
|
|
||||||
|
public GHUser getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwner(GHUser owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getExternalUrl() {
|
||||||
|
return externalUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExternalUrl(String externalUrl) {
|
||||||
|
this.externalUrl = externalUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GHEvent> getEvents() {
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEvents(List<GHEvent> events) {
|
||||||
|
this.events = events;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getInstallationsCount() {
|
||||||
|
return installationsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInstallationsCount(long installationsCount) {
|
||||||
|
this.installationsCount = installationsCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL getHtmlUrl() {
|
||||||
|
return GitHub.parseURL(htmlUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getPermissions() {
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermissions(Map<String, String> permissions) {
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ GHApp wrapUp(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains all the installations associated with this app.
|
||||||
|
*
|
||||||
|
* You must use a JWT to access this endpoint.
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/apps/#list-installations">List installations</a>
|
||||||
|
* @return a list of App installations
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public PagedIterable<GHAppInstallation> listInstallations() {
|
||||||
|
return root.retrieve().withPreview(MACHINE_MAN)
|
||||||
|
.asPagedIterable(
|
||||||
|
"/app/installations",
|
||||||
|
GHAppInstallation[].class,
|
||||||
|
item -> item.wrapUp(root) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain an installation associated with this app
|
||||||
|
* @param id - Installation Id
|
||||||
|
*
|
||||||
|
* You must use a JWT to access this endpoint.
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/apps/#get-an-installation">Get an installation</a>
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHAppInstallation getInstallationById(long id) throws IOException {
|
||||||
|
return root.retrieve().withPreview(MACHINE_MAN).to(String.format("/app/installations/%d", id), GHAppInstallation.class).wrapUp(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain an organization installation associated with this app
|
||||||
|
* @param name - Organization name
|
||||||
|
*
|
||||||
|
* You must use a JWT to access this endpoint.
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/apps/#get-an-organization-installation">Get an organization installation</a>
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHAppInstallation getInstallationByOrganization(String name) throws IOException {
|
||||||
|
return root.retrieve().withPreview(MACHINE_MAN).to(String.format("/orgs/%s/installation", name), GHAppInstallation.class).wrapUp(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain an repository installation associated with this app
|
||||||
|
* @param ownerName - Organization or user name
|
||||||
|
* @param repositoryName - Repository name
|
||||||
|
*
|
||||||
|
* You must use a JWT to access this endpoint.
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/apps/#get-a-repository-installation">Get a repository installation</a>
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHAppInstallation getInstallationByRepository(String ownerName, String repositoryName) throws IOException {
|
||||||
|
return root.retrieve().withPreview(MACHINE_MAN).to(String.format("/repos/%s/%s/installation", ownerName, repositoryName), GHAppInstallation.class).wrapUp(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtain a user installation associated with this app
|
||||||
|
* @param name - user name
|
||||||
|
*
|
||||||
|
* You must use a JWT to access this endpoint.
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/apps/#get-a-user-installation">Get a user installation</a>
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHAppInstallation getInstallationByUser(String name) throws IOException {
|
||||||
|
return root.retrieve().withPreview(MACHINE_MAN).to(String.format("/users/%s/installation", name), GHAppInstallation.class).wrapUp(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.MACHINE_MAN;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a access token for a GitHub App Installation
|
||||||
|
*
|
||||||
|
* @author Paulo Miguel Almeida
|
||||||
|
*
|
||||||
|
* @see GHAppInstallation#createToken(Map)
|
||||||
|
*/
|
||||||
|
public class GHAppCreateTokenBuilder {
|
||||||
|
private final GitHub root;
|
||||||
|
protected final Requester builder;
|
||||||
|
private final String apiUrlTail;
|
||||||
|
|
||||||
|
@Preview @Deprecated
|
||||||
|
/*package*/ GHAppCreateTokenBuilder(GitHub root, String apiUrlTail, Map<String, GHPermissionType> permissions) {
|
||||||
|
this.root = root;
|
||||||
|
this.apiUrlTail = apiUrlTail;
|
||||||
|
this.builder = new Requester(root);
|
||||||
|
this.builder.withPermissions("permissions",permissions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* By default the installation token has access to all repositories that the installation can access. To restrict
|
||||||
|
* the access to specific repositories, you can provide the repository_ids when creating the token. When you omit
|
||||||
|
* repository_ids, the response does not contain neither the repositories nor the permissions key.
|
||||||
|
*
|
||||||
|
* @param repositoryIds - Array containing the repositories Ids
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHAppCreateTokenBuilder repositoryIds(List<Long> repositoryIds) {
|
||||||
|
this.builder.with("repository_ids",repositoryIds);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an app token with all the parameters.
|
||||||
|
*
|
||||||
|
* You must use a JWT to access this endpoint.
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHAppInstallationToken create() throws IOException {
|
||||||
|
return builder.method("POST").withPreview(MACHINE_MAN).to(apiUrlTail, GHAppInstallationToken.class).wrapUp(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
167
src/main/java/org/kohsuke/github/GHAppInstallation.java
Normal file
167
src/main/java/org/kohsuke/github/GHAppInstallation.java
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.GAMBIT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Github App Installation.
|
||||||
|
*
|
||||||
|
* @author Paulo Miguel Almeida
|
||||||
|
*
|
||||||
|
* @see GHApp#listInstallations()
|
||||||
|
* @see GHApp#getInstallationById(long)
|
||||||
|
* @see GHApp#getInstallationByOrganization(String)
|
||||||
|
* @see GHApp#getInstallationByRepository(String, String)
|
||||||
|
* @see GHApp#getInstallationByUser(String)
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class GHAppInstallation extends GHObject {
|
||||||
|
private GitHub root;
|
||||||
|
private GHUser account;
|
||||||
|
|
||||||
|
@JsonProperty("access_tokens_url")
|
||||||
|
private String accessTokenUrl;
|
||||||
|
@JsonProperty("repositories_url")
|
||||||
|
private String repositoriesUrl;
|
||||||
|
@JsonProperty("app_id")
|
||||||
|
private long appId;
|
||||||
|
@JsonProperty("target_id")
|
||||||
|
private long targetId;
|
||||||
|
@JsonProperty("target_type")
|
||||||
|
private GHTargetType targetType;
|
||||||
|
private Map<String, GHPermissionType> permissions;
|
||||||
|
private List<GHEvent> events;
|
||||||
|
@JsonProperty("single_file_name")
|
||||||
|
private String singleFileName;
|
||||||
|
@JsonProperty("repository_selection")
|
||||||
|
private GHRepositorySelection repositorySelection;
|
||||||
|
private String htmlUrl;
|
||||||
|
|
||||||
|
public URL getHtmlUrl() {
|
||||||
|
return GitHub.parseURL(htmlUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitHub getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoot(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHUser getAccount() {
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccount(GHUser account) {
|
||||||
|
this.account = account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccessTokenUrl() {
|
||||||
|
return accessTokenUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccessTokenUrl(String accessTokenUrl) {
|
||||||
|
this.accessTokenUrl = accessTokenUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRepositoriesUrl() {
|
||||||
|
return repositoriesUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepositoriesUrl(String repositoriesUrl) {
|
||||||
|
this.repositoriesUrl = repositoriesUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getAppId() {
|
||||||
|
return appId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppId(long appId) {
|
||||||
|
this.appId = appId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTargetId() {
|
||||||
|
return targetId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetId(long targetId) {
|
||||||
|
this.targetId = targetId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHTargetType getTargetType() {
|
||||||
|
return targetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetType(GHTargetType targetType) {
|
||||||
|
this.targetType = targetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, GHPermissionType> getPermissions() {
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermissions(Map<String, GHPermissionType> permissions) {
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GHEvent> getEvents() {
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEvents(List<GHEvent> events) {
|
||||||
|
this.events = events;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSingleFileName() {
|
||||||
|
return singleFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSingleFileName(String singleFileName) {
|
||||||
|
this.singleFileName = singleFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepositorySelection getRepositorySelection() {
|
||||||
|
return repositorySelection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepositorySelection(GHRepositorySelection repositorySelection) {
|
||||||
|
this.repositorySelection = repositorySelection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ GHAppInstallation wrapUp(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a Github App installation
|
||||||
|
*
|
||||||
|
* You must use a JWT to access this endpoint.
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/apps/#delete-an-installation">Delete an installation</a>
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public void deleteInstallation() throws IOException {
|
||||||
|
root.retrieve().method("DELETE").withPreview(GAMBIT).to(String.format("/app/installations/%d", id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a builder that creates a new App Installation Token.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* You use the returned builder to set various properties, then call {@link GHAppCreateTokenBuilder#create()}
|
||||||
|
* to finally create an access token.
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHAppCreateTokenBuilder createToken(Map<String,GHPermissionType> permissions){
|
||||||
|
return new GHAppCreateTokenBuilder(root,String.format("/app/installations/%d/access_tokens", id), permissions);
|
||||||
|
}
|
||||||
|
}
|
||||||
87
src/main/java/org/kohsuke/github/GHAppInstallationToken.java
Normal file
87
src/main/java/org/kohsuke/github/GHAppInstallationToken.java
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Github App Installation Token.
|
||||||
|
*
|
||||||
|
* @author Paulo Miguel Almeida
|
||||||
|
*
|
||||||
|
* @see GHAppInstallation#createToken(Map)
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class GHAppInstallationToken {
|
||||||
|
private GitHub root;
|
||||||
|
|
||||||
|
private String token;
|
||||||
|
protected String expires_at;
|
||||||
|
private Map<String, String> permissions;
|
||||||
|
private List<GHRepository> repositories;
|
||||||
|
@JsonProperty("repository_selection")
|
||||||
|
private GHRepositorySelection repositorySelection;
|
||||||
|
|
||||||
|
public GitHub getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoot(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getPermissions() {
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermissions(Map<String, String> permissions) {
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GHRepository> getRepositories() {
|
||||||
|
return repositories;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepositories(List<GHRepository> repositories) {
|
||||||
|
this.repositories = repositories;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepositorySelection getRepositorySelection() {
|
||||||
|
return repositorySelection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepositorySelection(GHRepositorySelection repositorySelection) {
|
||||||
|
this.repositorySelection = repositorySelection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When was this tokens expires?
|
||||||
|
*/
|
||||||
|
@WithBridgeMethods(value=String.class, adapterMethod="expiresAtStr")
|
||||||
|
public Date getExpiresAt() throws IOException {
|
||||||
|
return GitHub.parseDate(expires_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getExpiresAt")
|
||||||
|
private Object expiresAtStr(Date id, Class type) {
|
||||||
|
return expires_at;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ GHAppInstallationToken wrapUp(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,9 +36,14 @@ public class GHAuthorization extends GHObject {
|
|||||||
private GitHub root;
|
private GitHub root;
|
||||||
private List<String> scopes;
|
private List<String> scopes;
|
||||||
private String token;
|
private String token;
|
||||||
|
private String token_last_eight;
|
||||||
|
private String hashed_token;
|
||||||
private App app;
|
private App app;
|
||||||
private String note;
|
private String note;
|
||||||
private String note_url;
|
private String note_url;
|
||||||
|
private String fingerprint;
|
||||||
|
//TODO add some user class for https://developer.github.com/v3/oauth_authorizations/#check-an-authorization ?
|
||||||
|
//private GHUser user;
|
||||||
|
|
||||||
public GitHub getRoot() {
|
public GitHub getRoot() {
|
||||||
return root;
|
return root;
|
||||||
@@ -52,6 +57,14 @@ public class GHAuthorization extends GHObject {
|
|||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTokenLastEight() {
|
||||||
|
return token_last_eight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHashedToken() {
|
||||||
|
return hashed_token;
|
||||||
|
}
|
||||||
|
|
||||||
public URL getAppUrl() {
|
public URL getAppUrl() {
|
||||||
return GitHub.parseURL(app.url);
|
return GitHub.parseURL(app.url);
|
||||||
}
|
}
|
||||||
@@ -82,6 +95,10 @@ public class GHAuthorization extends GHObject {
|
|||||||
return GitHub.parseURL(note_url);
|
return GitHub.parseURL(note_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getFingerprint() {
|
||||||
|
return fingerprint;
|
||||||
|
}
|
||||||
|
|
||||||
/*package*/ GHAuthorization wrap(GitHub root) {
|
/*package*/ GHAuthorization wrap(GitHub root) {
|
||||||
this.root = root;
|
this.root = root;
|
||||||
return this;
|
return this;
|
||||||
@@ -92,5 +109,6 @@ public class GHAuthorization extends GHObject {
|
|||||||
private static class App {
|
private static class App {
|
||||||
private String url;
|
private String url;
|
||||||
private String name;
|
private String name;
|
||||||
|
// private String client_id; not yet used
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
64
src/main/java/org/kohsuke/github/GHBlob.java
Normal file
64
src/main/java/org/kohsuke/github/GHBlob.java
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64InputStream;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kanstantsin Shautsou
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
* @see GHTreeEntry#asBlob()
|
||||||
|
* @see GHRepository#getBlob(String)
|
||||||
|
* @see <a href="https://developer.github.com/v3/git/blobs/#get-a-blob">Get a blob</a>
|
||||||
|
*/
|
||||||
|
public class GHBlob {
|
||||||
|
private String content, encoding, url, sha;
|
||||||
|
private long size;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* API URL of this blob.
|
||||||
|
*/
|
||||||
|
public URL getUrl() {
|
||||||
|
return GitHub.parseURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSha() {
|
||||||
|
return sha;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Number of bytes in this blob.
|
||||||
|
*/
|
||||||
|
public long getSize() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEncoding() {
|
||||||
|
return encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encoded content. You probably want {@link #read()}
|
||||||
|
*/
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the actual bytes of the blob.
|
||||||
|
*/
|
||||||
|
public InputStream read() {
|
||||||
|
if (encoding.equals("base64")) {
|
||||||
|
try {
|
||||||
|
return new Base64InputStream(new ByteArrayInputStream(content.getBytes("US-ASCII")), false);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new AssertionError(e); // US-ASCII is mandatory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnsupportedOperationException("Unrecognized encoding: "+encoding);
|
||||||
|
}
|
||||||
|
}
|
||||||
49
src/main/java/org/kohsuke/github/GHBlobBuilder.java
Normal file
49
src/main/java/org/kohsuke/github/GHBlobBuilder.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder pattern for creating a new blob.
|
||||||
|
* Based on https://developer.github.com/v3/git/blobs/#create-a-blob
|
||||||
|
*/
|
||||||
|
public class GHBlobBuilder {
|
||||||
|
private final GHRepository repo;
|
||||||
|
private final Requester req;
|
||||||
|
|
||||||
|
GHBlobBuilder(GHRepository repo) {
|
||||||
|
this.repo = repo;
|
||||||
|
req = new Requester(repo.root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures a blob with the specified text {@code content}.
|
||||||
|
*/
|
||||||
|
public GHBlobBuilder textContent(String content) {
|
||||||
|
req.with("content", content);
|
||||||
|
req.with("encoding", "utf-8");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures a blob with the specified binary {@code content}.
|
||||||
|
*/
|
||||||
|
public GHBlobBuilder binaryContent(byte[] content) {
|
||||||
|
String base64Content = Base64.encodeBase64String(content);
|
||||||
|
req.with("content", base64Content);
|
||||||
|
req.with("encoding", "base64");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getApiTail() {
|
||||||
|
return String.format("/repos/%s/%s/git/blobs", repo.getOwnerName(), repo.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a blob based on the parameters specified thus far.
|
||||||
|
*/
|
||||||
|
public GHBlob create() throws IOException {
|
||||||
|
return req.method("POST").to(getApiTail(), GHBlob.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,35 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A branch in a repository.
|
* A branch in a repository.
|
||||||
*
|
*
|
||||||
* @author Yusuke Kokubo
|
* @author Yusuke Kokubo
|
||||||
*/
|
*/
|
||||||
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
|
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
|
||||||
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
|
"NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD"}, justification = "JSON API")
|
||||||
public class GHBranch {
|
public class GHBranch {
|
||||||
private GitHub root;
|
private GitHub root;
|
||||||
private GHRepository owner;
|
private GHRepository owner;
|
||||||
|
|
||||||
private String name;
|
private String name;
|
||||||
private Commit commit;
|
private Commit commit;
|
||||||
|
@JsonProperty("protected")
|
||||||
|
private boolean protection;
|
||||||
|
private String protection_url;
|
||||||
|
|
||||||
|
|
||||||
public static class Commit {
|
public static class Commit {
|
||||||
String sha;
|
String sha;
|
||||||
|
|
||||||
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
|
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
|
||||||
String url;
|
String url;
|
||||||
}
|
}
|
||||||
@@ -38,13 +49,71 @@ public class GHBranch {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the push to this branch is restricted via branch protection.
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public boolean isProtected() {
|
||||||
|
return protection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns API URL that deals with the protection of this branch.
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public URL getProtectionUrl() {
|
||||||
|
return GitHub.parseURL(protection_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtection getProtection() throws IOException {
|
||||||
|
return root.retrieve().to(protection_url, GHBranchProtection.class).wrap(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The commit that this branch currently points to.
|
* The commit that this branch currently points to.
|
||||||
*/
|
*/
|
||||||
public String getSHA1() {
|
public String getSHA1() {
|
||||||
return commit.sha;
|
return commit.sha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables branch protection and allows anyone with push access to push changes.
|
||||||
|
*/
|
||||||
|
public void disableProtection() throws IOException {
|
||||||
|
new Requester(root).method("DELETE").to(protection_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables branch protection to control what commit statuses are required to push.
|
||||||
|
*
|
||||||
|
* @see GHCommitStatus#getContext()
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHBranchProtectionBuilder enableProtection() {
|
||||||
|
return new GHBranchProtectionBuilder(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// backward compatibility with previous signature
|
||||||
|
@Deprecated
|
||||||
|
public void enableProtection(EnforcementLevel level, Collection<String> contexts) throws IOException {
|
||||||
|
switch (level) {
|
||||||
|
case OFF:
|
||||||
|
disableProtection();
|
||||||
|
break;
|
||||||
|
case NON_ADMINS:
|
||||||
|
case EVERYONE:
|
||||||
|
enableProtection()
|
||||||
|
.addRequiredChecks(contexts)
|
||||||
|
.includeAdmins(level==EnforcementLevel.EVERYONE)
|
||||||
|
.enable();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String getApiRoute() {
|
||||||
|
return owner.getApiTailUrl("/branches/"+name);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
final String url = owner != null ? owner.getUrl().toString() : "unknown";
|
final String url = owner != null ? owner.getUrl().toString() : "unknown";
|
||||||
|
|||||||
208
src/main/java/org/kohsuke/github/GHBranchProtection.java
Normal file
208
src/main/java/org/kohsuke/github/GHBranchProtection.java
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.ZZZAX;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD",
|
||||||
|
"URF_UNREAD_FIELD"}, justification = "JSON API")
|
||||||
|
public class GHBranchProtection {
|
||||||
|
private static final String REQUIRE_SIGNATURES_URI = "/required_signatures";
|
||||||
|
|
||||||
|
@JsonProperty("enforce_admins")
|
||||||
|
private EnforceAdmins enforceAdmins;
|
||||||
|
|
||||||
|
private GitHub root;
|
||||||
|
|
||||||
|
@JsonProperty("required_pull_request_reviews")
|
||||||
|
private RequiredReviews requiredReviews;
|
||||||
|
|
||||||
|
@JsonProperty("required_status_checks")
|
||||||
|
private RequiredStatusChecks requiredStatusChecks;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private Restrictions restrictions;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@Preview @Deprecated
|
||||||
|
public void enabledSignedCommits() throws IOException {
|
||||||
|
requester().method("POST")
|
||||||
|
.to(url + REQUIRE_SIGNATURES_URI, RequiredSignatures.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview @Deprecated
|
||||||
|
public void disableSignedCommits() throws IOException {
|
||||||
|
requester().method("DELETE")
|
||||||
|
.to(url + REQUIRE_SIGNATURES_URI);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EnforceAdmins getEnforceAdmins() {
|
||||||
|
return enforceAdmins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RequiredReviews getRequiredReviews() {
|
||||||
|
return requiredReviews;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview @Deprecated
|
||||||
|
public boolean getRequiredSignatures() throws IOException {
|
||||||
|
return requester().method("GET")
|
||||||
|
.to(url + REQUIRE_SIGNATURES_URI, RequiredSignatures.class).enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RequiredStatusChecks getRequiredStatusChecks() {
|
||||||
|
return requiredStatusChecks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Restrictions getRestrictions() {
|
||||||
|
return restrictions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHBranchProtection wrap(GHBranch branch) {
|
||||||
|
this.root = branch.getRoot();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Requester requester() {
|
||||||
|
return new Requester(root).withPreview(ZZZAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EnforceAdmins {
|
||||||
|
@JsonProperty
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RequiredReviews {
|
||||||
|
@JsonProperty("dismissal_restrictions")
|
||||||
|
private Restrictions dismissalRestriction;
|
||||||
|
|
||||||
|
@JsonProperty("dismiss_stale_reviews")
|
||||||
|
private boolean dismissStaleReviews;
|
||||||
|
|
||||||
|
@JsonProperty("require_code_owner_reviews")
|
||||||
|
private boolean requireCodeOwnerReviews;
|
||||||
|
|
||||||
|
@JsonProperty("required_approving_review_count")
|
||||||
|
private int requiredReviewers;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
public Restrictions getDismissalRestrictions() {
|
||||||
|
return dismissalRestriction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDismissStaleReviews() {
|
||||||
|
return dismissStaleReviews;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRequireCodeOwnerReviews() {
|
||||||
|
return requireCodeOwnerReviews;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRequiredReviewers() {
|
||||||
|
return requiredReviewers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class RequiredSignatures {
|
||||||
|
@JsonProperty
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class RequiredStatusChecks {
|
||||||
|
@JsonProperty
|
||||||
|
private Collection<String> contexts;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private boolean strict;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
public Collection<String> getContexts() {
|
||||||
|
return contexts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRequiresBranchUpToDate() {
|
||||||
|
return strict;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Restrictions {
|
||||||
|
@JsonProperty
|
||||||
|
private Collection<GHTeam> teams;
|
||||||
|
|
||||||
|
@JsonProperty("teams_url")
|
||||||
|
private String teamsUrl;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
private Collection<GHUser> users;
|
||||||
|
|
||||||
|
@JsonProperty("users_url")
|
||||||
|
private String usersUrl;
|
||||||
|
|
||||||
|
public Collection<GHTeam> getTeams() {
|
||||||
|
return teams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTeamsUrl() {
|
||||||
|
return teamsUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<GHUser> getUsers() {
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsersUrl() {
|
||||||
|
return usersUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
218
src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java
Normal file
218
src/main/java/org/kohsuke/github/GHBranchProtectionBuilder.java
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder to configure the branch protection settings.
|
||||||
|
*
|
||||||
|
* @see GHBranch#enableProtection()
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = { "UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD",
|
||||||
|
"URF_UNREAD_FIELD" }, justification = "JSON API")
|
||||||
|
public class GHBranchProtectionBuilder {
|
||||||
|
private final GHBranch branch;
|
||||||
|
|
||||||
|
private boolean enforceAdmins;
|
||||||
|
private Map<String, Object> prReviews;
|
||||||
|
private Restrictions restrictions;
|
||||||
|
private StatusChecks statusChecks;
|
||||||
|
|
||||||
|
GHBranchProtectionBuilder(GHBranch branch) {
|
||||||
|
this.branch = branch;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder addRequiredChecks(Collection<String> checks) {
|
||||||
|
getStatusChecks().contexts.addAll(checks);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder addRequiredChecks(String... checks) {
|
||||||
|
addRequiredChecks(Arrays.asList(checks));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder dismissStaleReviews() {
|
||||||
|
return dismissStaleReviews(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder dismissStaleReviews(boolean v) {
|
||||||
|
getPrReviews().put("dismiss_stale_reviews", v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtection enable() throws IOException {
|
||||||
|
return requester().method("PUT")
|
||||||
|
.withNullable("required_status_checks", statusChecks)
|
||||||
|
.withNullable("required_pull_request_reviews", prReviews)
|
||||||
|
.withNullable("restrictions", restrictions)
|
||||||
|
.withNullable("enforce_admins", enforceAdmins)
|
||||||
|
.to(branch.getProtectionUrl().toString(), GHBranchProtection.class)
|
||||||
|
.wrap(branch);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder includeAdmins() {
|
||||||
|
return includeAdmins(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder includeAdmins(boolean v) {
|
||||||
|
enforceAdmins = v;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder requiredReviewers(int v) {
|
||||||
|
getPrReviews().put("required_approving_review_count", v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder requireBranchIsUpToDate() {
|
||||||
|
return requireBranchIsUpToDate(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder requireBranchIsUpToDate(boolean v) {
|
||||||
|
getStatusChecks().strict = v;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder requireCodeOwnReviews() {
|
||||||
|
return requireCodeOwnReviews(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder requireCodeOwnReviews(boolean v) {
|
||||||
|
getPrReviews().put("require_code_owner_reviews", v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder requireReviews() {
|
||||||
|
getPrReviews();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder restrictReviewDismissals() {
|
||||||
|
getPrReviews();
|
||||||
|
|
||||||
|
if (!prReviews.containsKey("dismissal_restrictions")) {
|
||||||
|
prReviews.put("dismissal_restrictions", new Restrictions());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder restrictPushAccess() {
|
||||||
|
getRestrictions();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder teamPushAccess(Collection<GHTeam> teams) {
|
||||||
|
for (GHTeam team : teams) {
|
||||||
|
teamPushAccess(team);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder teamPushAccess(GHTeam... teams) {
|
||||||
|
for (GHTeam team : teams) {
|
||||||
|
getRestrictions().teams.add(team.getSlug());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder teamReviewDismissals(Collection<GHTeam> teams) {
|
||||||
|
for (GHTeam team : teams) {
|
||||||
|
teamReviewDismissals(team);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder teamReviewDismissals(GHTeam... teams) {
|
||||||
|
for (GHTeam team : teams) {
|
||||||
|
addReviewRestriction(team.getSlug(), true);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder userPushAccess(Collection<GHUser> users) {
|
||||||
|
for (GHUser user : users) {
|
||||||
|
userPushAccess(user);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder userPushAccess(GHUser... users) {
|
||||||
|
for (GHUser user : users) {
|
||||||
|
getRestrictions().users.add(user.getLogin());
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder userReviewDismissals(Collection<GHUser> users) {
|
||||||
|
for (GHUser team : users) {
|
||||||
|
userReviewDismissals(team);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHBranchProtectionBuilder userReviewDismissals(GHUser... users) {
|
||||||
|
for (GHUser user : users) {
|
||||||
|
addReviewRestriction(user.getLogin(), false);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addReviewRestriction(String restriction, boolean isTeam) {
|
||||||
|
restrictReviewDismissals();
|
||||||
|
Restrictions restrictions = (Restrictions) prReviews.get("dismissal_restrictions");
|
||||||
|
|
||||||
|
if (isTeam) {
|
||||||
|
restrictions.teams.add(restriction);
|
||||||
|
} else {
|
||||||
|
restrictions.users.add(restriction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getPrReviews() {
|
||||||
|
if (prReviews == null) {
|
||||||
|
prReviews = new HashMap<String, Object>();
|
||||||
|
}
|
||||||
|
return prReviews;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Restrictions getRestrictions() {
|
||||||
|
if (restrictions == null) {
|
||||||
|
restrictions = new Restrictions();
|
||||||
|
}
|
||||||
|
return restrictions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StatusChecks getStatusChecks() {
|
||||||
|
if (statusChecks == null) {
|
||||||
|
statusChecks = new StatusChecks();
|
||||||
|
}
|
||||||
|
return statusChecks;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Requester requester() {
|
||||||
|
return new Requester(branch.getRoot()).withPreview(LUKE_CAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Restrictions {
|
||||||
|
private Set<String> teams = new HashSet<String>();
|
||||||
|
private Set<String> users = new HashSet<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class StatusChecks {
|
||||||
|
final List<String> contexts = new ArrayList<String>();
|
||||||
|
boolean strict;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How is an user associated with a repository?
|
||||||
|
*
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
*/
|
||||||
|
public enum GHCommentAuthorAssociation {
|
||||||
|
/**
|
||||||
|
* Author has been invited to collaborate on the repository.
|
||||||
|
*/
|
||||||
|
COLLABORATOR,
|
||||||
|
/**
|
||||||
|
* Author has previously committed to the repository.
|
||||||
|
*/
|
||||||
|
CONTRIBUTOR,
|
||||||
|
/**
|
||||||
|
* Author has not previously committed to GitHub.
|
||||||
|
*/
|
||||||
|
FIRST_TIMER,
|
||||||
|
/**
|
||||||
|
* Author has not previously committed to the repository.
|
||||||
|
*/
|
||||||
|
FIRST_TIME_CONTRIBUTOR,
|
||||||
|
/**
|
||||||
|
* Author is a member of the organization that owns the repository.
|
||||||
|
*/
|
||||||
|
MEMBER,
|
||||||
|
/**
|
||||||
|
* Author has no association with the repository.
|
||||||
|
*/
|
||||||
|
NONE,
|
||||||
|
/**
|
||||||
|
* Author is the owner of the repository.
|
||||||
|
*/
|
||||||
|
OWNER
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import java.net.URL;
|
|||||||
import java.util.AbstractList;
|
import java.util.AbstractList;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,16 +38,30 @@ public class GHCommit {
|
|||||||
|
|
||||||
private int comment_count;
|
private int comment_count;
|
||||||
|
|
||||||
|
static class Tree {
|
||||||
|
String sha;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Tree tree;
|
||||||
|
|
||||||
@WithBridgeMethods(value = GHAuthor.class, castRequired = true)
|
@WithBridgeMethods(value = GHAuthor.class, castRequired = true)
|
||||||
public GitUser getAuthor() {
|
public GitUser getAuthor() {
|
||||||
return author;
|
return author;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Date getAuthoredDate() {
|
||||||
|
return GitHub.parseDate(author.date);
|
||||||
|
}
|
||||||
|
|
||||||
@WithBridgeMethods(value = GHAuthor.class, castRequired = true)
|
@WithBridgeMethods(value = GHAuthor.class, castRequired = true)
|
||||||
public GitUser getCommitter() {
|
public GitUser getCommitter() {
|
||||||
return committer;
|
return committer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Date getCommitDate() {
|
||||||
|
return GitHub.parseDate(committer.date);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commit message.
|
* Commit message.
|
||||||
*/
|
*/
|
||||||
@@ -63,6 +78,7 @@ public class GHCommit {
|
|||||||
* @deprecated Use {@link GitUser} instead.
|
* @deprecated Use {@link GitUser} instead.
|
||||||
*/
|
*/
|
||||||
public static class GHAuthor extends GitUser {
|
public static class GHAuthor extends GitUser {
|
||||||
|
private String date;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Stats {
|
public static class Stats {
|
||||||
@@ -179,7 +195,8 @@ public class GHCommit {
|
|||||||
|
|
||||||
|
|
||||||
public ShortInfo getCommitShortInfo() throws IOException {
|
public ShortInfo getCommitShortInfo() throws IOException {
|
||||||
populate();
|
if (commit==null)
|
||||||
|
populate();
|
||||||
return commit;
|
return commit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,6 +231,13 @@ public class GHCommit {
|
|||||||
return stats.deletions;
|
return stats.deletions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use this method to walk the tree
|
||||||
|
*/
|
||||||
|
public GHTree getTree() throws IOException {
|
||||||
|
return owner.getTree(getCommitShortInfo().tree.sha);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URL of this commit like "https://github.com/kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000"
|
* URL of this commit like "https://github.com/kohsuke/sandbox-ant/commit/8ae38db0ea5837313ab5f39d43a6f73de3bd9000"
|
||||||
*/
|
*/
|
||||||
@@ -271,10 +295,29 @@ public class GHCommit {
|
|||||||
return resolveUser(author);
|
return resolveUser(author);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the date the change was authored on.
|
||||||
|
* @return the date the change was authored on.
|
||||||
|
* @throws IOException if the information was not already fetched and an attempt at fetching the information failed.
|
||||||
|
*/
|
||||||
|
public Date getAuthoredDate() throws IOException {
|
||||||
|
return getCommitShortInfo().getAuthoredDate();
|
||||||
|
}
|
||||||
|
|
||||||
public GHUser getCommitter() throws IOException {
|
public GHUser getCommitter() throws IOException {
|
||||||
return resolveUser(committer);
|
return resolveUser(committer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the date the change was committed on.
|
||||||
|
*
|
||||||
|
* @return the date the change was committed on.
|
||||||
|
* @throws IOException if the information was not already fetched and an attempt at fetching the information failed.
|
||||||
|
*/
|
||||||
|
public Date getCommitDate() throws IOException {
|
||||||
|
return getCommitShortInfo().getCommitDate();
|
||||||
|
}
|
||||||
|
|
||||||
private GHUser resolveUser(User author) throws IOException {
|
private GHUser resolveUser(User author) throws IOException {
|
||||||
if (author==null || author.login==null) return null;
|
if (author==null || author.login==null) return null;
|
||||||
return owner.root.getUser(author.login);
|
return owner.root.getUser(author.login);
|
||||||
@@ -284,17 +327,11 @@ public class GHCommit {
|
|||||||
* Lists up all the commit comments in this repository.
|
* Lists up all the commit comments in this repository.
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHCommitComment> listComments() {
|
public PagedIterable<GHCommitComment> listComments() {
|
||||||
return new PagedIterable<GHCommitComment>() {
|
return owner.root.retrieve()
|
||||||
public PagedIterator<GHCommitComment> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHCommitComment>(owner.root.retrieve().asIterator(String.format("/repos/%s/%s/commits/%s/comments", owner.getOwnerName(), owner.getName(), sha), GHCommitComment[].class, pageSize)) {
|
String.format("/repos/%s/%s/commits/%s/comments", owner.getOwnerName(), owner.getName(), sha),
|
||||||
@Override
|
GHCommitComment[].class,
|
||||||
protected void wrapUp(GHCommitComment[] page) {
|
item -> item.wrap(owner) );
|
||||||
for (GHCommitComment c : page)
|
|
||||||
c.wrap(owner);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
92
src/main/java/org/kohsuke/github/GHCommitBuilder.java
Normal file
92
src/main/java/org/kohsuke/github/GHCommitBuilder.java
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder pattern for creating a new commit.
|
||||||
|
* Based on https://developer.github.com/v3/git/commits/#create-a-commit
|
||||||
|
*/
|
||||||
|
public class GHCommitBuilder {
|
||||||
|
private final GHRepository repo;
|
||||||
|
private final Requester req;
|
||||||
|
|
||||||
|
private final List<String> parents = new ArrayList<String>();
|
||||||
|
|
||||||
|
private static final class UserInfo {
|
||||||
|
private final String name;
|
||||||
|
private final String email;
|
||||||
|
private final String date;
|
||||||
|
|
||||||
|
private UserInfo(String name, String email, Date date) {
|
||||||
|
this.name = name;
|
||||||
|
this.email = email;
|
||||||
|
TimeZone tz = TimeZone.getTimeZone("UTC");
|
||||||
|
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||||
|
df.setTimeZone(tz);
|
||||||
|
this.date = df.format((date != null) ? date : new Date());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GHCommitBuilder(GHRepository repo) {
|
||||||
|
this.repo = repo;
|
||||||
|
req = new Requester(repo.root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message the commit message
|
||||||
|
*/
|
||||||
|
public GHCommitBuilder message(String message) {
|
||||||
|
req.with("message", message);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tree the SHA of the tree object this commit points to
|
||||||
|
*/
|
||||||
|
public GHCommitBuilder tree(String tree) {
|
||||||
|
req.with("tree", tree);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param parent the SHA of a parent commit.
|
||||||
|
*/
|
||||||
|
public GHCommitBuilder parent(String parent) {
|
||||||
|
parents.add(parent);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the author of this commit.
|
||||||
|
*/
|
||||||
|
public GHCommitBuilder author(String name, String email, Date date) {
|
||||||
|
req._with("author", new UserInfo(name, email, date));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the committer of this commit.
|
||||||
|
*/
|
||||||
|
public GHCommitBuilder committer(String name, String email, Date date) {
|
||||||
|
req._with("committer", new UserInfo(name, email, date));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getApiTail() {
|
||||||
|
return String.format("/repos/%s/%s/git/commits", repo.getOwnerName(), repo.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a blob based on the parameters specified thus far.
|
||||||
|
*/
|
||||||
|
public GHCommit create() throws IOException {
|
||||||
|
req._with("parents", parents);
|
||||||
|
return req.method("POST").to(getApiTail(), GHCommit.class).wrapUp(repo);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Date;
|
|
||||||
|
import static org.kohsuke.github.Previews.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A comment attached to a commit (or a specific line in a specific file of a commit.)
|
* A comment attached to a commit (or a specific line in a specific file of a commit.)
|
||||||
@@ -15,23 +17,13 @@ import java.util.Date;
|
|||||||
*/
|
*/
|
||||||
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
|
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
|
||||||
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
|
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
|
||||||
public class GHCommitComment extends GHObject {
|
public class GHCommitComment extends GHObject implements Reactable {
|
||||||
private GHRepository owner;
|
private GHRepository owner;
|
||||||
|
|
||||||
String body, html_url, commit_id;
|
String body, html_url, commit_id;
|
||||||
Integer line;
|
Integer line;
|
||||||
String path;
|
String path;
|
||||||
User user;
|
GHUser user; // not fully populated. beware.
|
||||||
|
|
||||||
static class User {
|
|
||||||
// TODO: what if someone who doesn't have an account on GitHub makes a commit?
|
|
||||||
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
|
|
||||||
String url,avatar_url,gravatar_id;
|
|
||||||
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
|
|
||||||
int id;
|
|
||||||
|
|
||||||
String login;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GHRepository getOwner() {
|
public GHRepository getOwner() {
|
||||||
return owner;
|
return owner;
|
||||||
@@ -76,7 +68,7 @@ public class GHCommitComment extends GHObject {
|
|||||||
* Gets the user who put this comment.
|
* Gets the user who put this comment.
|
||||||
*/
|
*/
|
||||||
public GHUser getUser() throws IOException {
|
public GHUser getUser() throws IOException {
|
||||||
return owner.root.getUser(user.login);
|
return owner == null || owner.root.isOffline() ? user : owner.root.getUser(user.login);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,6 +88,23 @@ public class GHCommitComment extends GHObject {
|
|||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHReaction createReaction(ReactionContent content) throws IOException {
|
||||||
|
return new Requester(owner.root)
|
||||||
|
.withPreview(SQUIRREL_GIRL)
|
||||||
|
.with("content", content.getContent())
|
||||||
|
.to(getApiTail()+"/reactions", GHReaction.class).wrap(owner.root);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview @Deprecated
|
||||||
|
public PagedIterable<GHReaction> listReactions() {
|
||||||
|
return owner.root.retrieve().withPreview(SQUIRREL_GIRL)
|
||||||
|
.asPagedIterable(
|
||||||
|
getApiTail()+"/reactions",
|
||||||
|
GHReaction[].class,
|
||||||
|
item -> item.wrap(owner.root) );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes this comment.
|
* Deletes this comment.
|
||||||
*/
|
*/
|
||||||
@@ -110,6 +119,9 @@ public class GHCommitComment extends GHObject {
|
|||||||
|
|
||||||
GHCommitComment wrap(GHRepository owner) {
|
GHCommitComment wrap(GHRepository owner) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
|
if (owner.root.isOffline()) {
|
||||||
|
user.wrapUp(owner.root);
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,8 @@ public class GHCommitPointer {
|
|||||||
* This points to the user who owns
|
* This points to the user who owns
|
||||||
* the {@link #getRepository()}.
|
* the {@link #getRepository()}.
|
||||||
*/
|
*/
|
||||||
public GHUser getUser() {
|
public GHUser getUser() throws IOException {
|
||||||
|
if (user != null) return user.root.intern(user);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -91,15 +91,10 @@ public class GHCommitQueryBuilder {
|
|||||||
* Lists up the commits with the criteria built so far.
|
* Lists up the commits with the criteria built so far.
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHCommit> list() {
|
public PagedIterable<GHCommit> list() {
|
||||||
return new PagedIterable<GHCommit>() {
|
return req
|
||||||
public PagedIterator<GHCommit> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHCommit>(req.asIterator(repo.getApiTailUrl("commits"), GHCommit[].class, pageSize)) {
|
repo.getApiTailUrl("commits"),
|
||||||
protected void wrapUp(GHCommit[] page) {
|
GHCommit[].class,
|
||||||
for (GHCommit c : page)
|
item -> item.wrapUp(repo) );
|
||||||
c.wrapUp(repo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
137
src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java
Normal file
137
src/main/java/org/kohsuke/github/GHCommitSearchBuilder.java
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search commits.
|
||||||
|
*
|
||||||
|
* @author Marc de Verdelhan
|
||||||
|
* @see GitHub#searchCommits()
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public class GHCommitSearchBuilder extends GHSearchBuilder<GHCommit> {
|
||||||
|
/*package*/ GHCommitSearchBuilder(GitHub root) {
|
||||||
|
super(root,CommitSearchResult.class);
|
||||||
|
req.withPreview(Previews.CLOAK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search terms.
|
||||||
|
*/
|
||||||
|
public GHCommitSearchBuilder q(String term) {
|
||||||
|
super.q(term);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder author(String v) {
|
||||||
|
return q("author:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder committer(String v) {
|
||||||
|
return q("committer:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder authorName(String v) {
|
||||||
|
return q("author-name:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder committerName(String v) {
|
||||||
|
return q("committer-name:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder authorEmail(String v) {
|
||||||
|
return q("author-email:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder committerEmail(String v) {
|
||||||
|
return q("committer-email:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder authorDate(String v) {
|
||||||
|
return q("author-date:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder committerDate(String v) {
|
||||||
|
return q("committer-date:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder merge(boolean merge) {
|
||||||
|
return q("merge:"+Boolean.valueOf(merge).toString().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder hash(String v) {
|
||||||
|
return q("hash:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder parent(String v) {
|
||||||
|
return q("parent:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder tree(String v) {
|
||||||
|
return q("tree:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder is(String v) {
|
||||||
|
return q("is:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder user(String v) {
|
||||||
|
return q("user:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder org(String v) {
|
||||||
|
return q("org:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder repo(String v) {
|
||||||
|
return q("repo:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder order(GHDirection v) {
|
||||||
|
req.with("order",v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitSearchBuilder sort(Sort sort) {
|
||||||
|
req.with("sort",sort);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Sort { AUTHOR_DATE, COMMITTER_DATE }
|
||||||
|
|
||||||
|
private static class CommitSearchResult extends SearchResult<GHCommit> {
|
||||||
|
private GHCommit[] items;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
/*package*/ GHCommit[] getItems(GitHub root) {
|
||||||
|
for (GHCommit commit : items) {
|
||||||
|
String repoName = getRepoName(commit.url);
|
||||||
|
try {
|
||||||
|
GHRepository repo = root.getRepository(repoName);
|
||||||
|
commit.wrapUp(repo);
|
||||||
|
} catch (IOException ioe) {}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param commitUrl a commit URL
|
||||||
|
* @return the repo name ("username/reponame")
|
||||||
|
*/
|
||||||
|
private static String getRepoName(String commitUrl) {
|
||||||
|
if (StringUtils.isBlank(commitUrl)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int indexOfUsername = (GitHub.GITHUB_URL + "/repos/").length();
|
||||||
|
String[] tokens = commitUrl.substring(indexOfUsername).split("/", 3);
|
||||||
|
return tokens[0] + '/' + tokens[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getApiUrl() {
|
||||||
|
return "/search/commits";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,6 @@ package org.kohsuke.github;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a status of a commit.
|
* Represents a status of a commit.
|
||||||
@@ -10,6 +9,7 @@ import java.util.Date;
|
|||||||
* @author Kohsuke Kawaguchi
|
* @author Kohsuke Kawaguchi
|
||||||
* @see GHRepository#getLastCommitStatus(String)
|
* @see GHRepository#getLastCommitStatus(String)
|
||||||
* @see GHCommit#getLastStatus()
|
* @see GHCommit#getLastStatus()
|
||||||
|
* @see GHRepository#createCommitStatus(String, GHCommitState, String, String)
|
||||||
*/
|
*/
|
||||||
public class GHCommitStatus extends GHObject {
|
public class GHCommitStatus extends GHObject {
|
||||||
String state;
|
String state;
|
||||||
@@ -46,8 +46,8 @@ public class GHCommitStatus extends GHObject {
|
|||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GHUser getCreator() {
|
public GHUser getCreator() throws IOException {
|
||||||
return creator;
|
return root.intern(creator);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getContext() {
|
public String getContext() {
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
|||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The model user for comparing 2 commits in the GitHub API.
|
* The model user for comparing 2 commits in the GitHub API.
|
||||||
@@ -72,7 +70,9 @@ public class GHCompare {
|
|||||||
* @return A copy of the array being stored in the class.
|
* @return A copy of the array being stored in the class.
|
||||||
*/
|
*/
|
||||||
public Commit[] getCommits() {
|
public Commit[] getCommits() {
|
||||||
return Arrays.copyOf(commits, commits.length);
|
Commit[] newValue = new Commit[commits.length];
|
||||||
|
System.arraycopy(commits, 0, newValue, 0, commits.length);
|
||||||
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,7 +80,9 @@ public class GHCompare {
|
|||||||
* @return A copy of the array being stored in the class.
|
* @return A copy of the array being stored in the class.
|
||||||
*/
|
*/
|
||||||
public GHCommit.File[] getFiles() {
|
public GHCommit.File[] getFiles() {
|
||||||
return Arrays.copyOf(files, files.length);
|
GHCommit.File[] newValue = new GHCommit.File[files.length];
|
||||||
|
System.arraycopy(files, 0, newValue, 0, files.length);
|
||||||
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GHCompare wrap(GHRepository owner) {
|
public GHCompare wrap(GHRepository owner) {
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package org.kohsuke.github;
|
|||||||
|
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.codec.binary.Base64InputStream;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
import javax.xml.bind.DatatypeConverter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Content of a repository.
|
* A Content of a repository.
|
||||||
@@ -16,7 +16,7 @@ import javax.xml.bind.DatatypeConverter;
|
|||||||
* @see GHRepository#getFileContent(String)
|
* @see GHRepository#getFileContent(String)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"UnusedDeclaration"})
|
@SuppressWarnings({"UnusedDeclaration"})
|
||||||
public class GHContent {
|
public class GHContent implements Refreshable {
|
||||||
/*
|
/*
|
||||||
In normal use of this class, repository field is set via wrap(),
|
In normal use of this class, repository field is set via wrap(),
|
||||||
but in the code search API, there's a nested 'repository' field that gets populated from JSON.
|
but in the code search API, there's a nested 'repository' field that gets populated from JSON.
|
||||||
@@ -78,7 +78,7 @@ public class GHContent {
|
|||||||
*/
|
*/
|
||||||
@SuppressFBWarnings("DM_DEFAULT_ENCODING")
|
@SuppressFBWarnings("DM_DEFAULT_ENCODING")
|
||||||
public String getContent() throws IOException {
|
public String getContent() throws IOException {
|
||||||
return new String(DatatypeConverter.parseBase64Binary(getEncodedContent()));
|
return new String(Base64.decodeBase64(getEncodedContent()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,10 +93,8 @@ public class GHContent {
|
|||||||
* Use {@link #read()}
|
* Use {@link #read()}
|
||||||
*/
|
*/
|
||||||
public String getEncodedContent() throws IOException {
|
public String getEncodedContent() throws IOException {
|
||||||
if (content!=null)
|
refresh(content);
|
||||||
return content;
|
return content;
|
||||||
else
|
|
||||||
return Base64.encodeBase64String(IOUtils.toByteArray(read()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
@@ -114,15 +112,27 @@ public class GHContent {
|
|||||||
/**
|
/**
|
||||||
* Retrieves the actual content stored here.
|
* Retrieves the actual content stored here.
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* Retrieves the actual bytes of the blob.
|
||||||
|
*/
|
||||||
public InputStream read() throws IOException {
|
public InputStream read() throws IOException {
|
||||||
return new Requester(root).asStream(getDownloadUrl());
|
refresh(content);
|
||||||
|
if (encoding.equals("base64")) {
|
||||||
|
try {
|
||||||
|
return new Base64InputStream(new ByteArrayInputStream(content.getBytes("US-ASCII")), false);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new AssertionError(e); // US-ASCII is mandatory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new UnsupportedOperationException("Unrecognized encoding: "+encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* URL to retrieve the raw content of the file. Null if this is a directory.
|
* URL to retrieve the raw content of the file. Null if this is a directory.
|
||||||
*/
|
*/
|
||||||
public String getDownloadUrl() throws IOException {
|
public String getDownloadUrl() throws IOException {
|
||||||
populate();
|
refresh(download_url);
|
||||||
return download_url;
|
return download_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +150,6 @@ public class GHContent {
|
|||||||
* Depending on the original API call where this object is created, it may not contain everything.
|
* Depending on the original API call where this object is created, it may not contain everything.
|
||||||
*/
|
*/
|
||||||
protected synchronized void populate() throws IOException {
|
protected synchronized void populate() throws IOException {
|
||||||
if (download_url!=null) return; // already populated
|
|
||||||
root.retrieve().to(url, this);
|
root.retrieve().to(url, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,16 +160,11 @@ public class GHContent {
|
|||||||
if (!isDirectory())
|
if (!isDirectory())
|
||||||
throw new IllegalStateException(path+" is not a directory");
|
throw new IllegalStateException(path+" is not a directory");
|
||||||
|
|
||||||
return new PagedIterable<GHContent>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHContent> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHContent>(root.retrieve().asIterator(url, GHContent[].class, pageSize)) {
|
url,
|
||||||
@Override
|
GHContent[].class,
|
||||||
protected void wrapUp(GHContent[] page) {
|
item -> item.wrap(repository) );
|
||||||
GHContent.wrap(page, repository);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressFBWarnings("DM_DEFAULT_ENCODING")
|
@SuppressFBWarnings("DM_DEFAULT_ENCODING")
|
||||||
@@ -178,7 +182,7 @@ public class GHContent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GHContentUpdateResponse update(byte[] newContentBytes, String commitMessage, String branch) throws IOException {
|
public GHContentUpdateResponse update(byte[] newContentBytes, String commitMessage, String branch) throws IOException {
|
||||||
String encodedContent = DatatypeConverter.printBase64Binary(newContentBytes);
|
String encodedContent = Base64.encodeBase64String(newContentBytes);
|
||||||
|
|
||||||
Requester requester = new Requester(root)
|
Requester requester = new Requester(root)
|
||||||
.with("path", path)
|
.with("path", path)
|
||||||
@@ -244,4 +248,14 @@ public class GHContent {
|
|||||||
}
|
}
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fully populate the data by retrieving missing data.
|
||||||
|
*
|
||||||
|
* Depending on the original API call where this object is created, it may not contain everything.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public synchronized void refresh() throws IOException {
|
||||||
|
root.retrieve().to(url, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
76
src/main/java/org/kohsuke/github/GHContentBuilder.java
Normal file
76
src/main/java/org/kohsuke/github/GHContentBuilder.java
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to create/update content.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Call various methods to build up parameters, then call {@link #commit()} to make the change effective.
|
||||||
|
*
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
* @see GHRepository#createContent()
|
||||||
|
*/
|
||||||
|
public final class GHContentBuilder {
|
||||||
|
private final GHRepository repo;
|
||||||
|
private final Requester req;
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
GHContentBuilder(GHRepository repo) {
|
||||||
|
this.repo = repo;
|
||||||
|
this.req = new Requester(repo.root).method("PUT");
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHContentBuilder path(String path) {
|
||||||
|
this.path = path;
|
||||||
|
req.with("path",path);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHContentBuilder branch(String branch) {
|
||||||
|
req.with("branch", branch);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used when updating (but not creating a new content) to specify
|
||||||
|
* Thetblob SHA of the file being replaced.
|
||||||
|
*/
|
||||||
|
public GHContentBuilder sha(String sha) {
|
||||||
|
req.with("sha", sha);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHContentBuilder content(byte[] content) {
|
||||||
|
req.with("content", Base64.encodeBase64String(content));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHContentBuilder content(String content) {
|
||||||
|
try {
|
||||||
|
return content(content.getBytes("UTF-8"));
|
||||||
|
} catch (UnsupportedEncodingException x) {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHContentBuilder message(String commitMessage) {
|
||||||
|
req.with("message", commitMessage);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commits a new content.
|
||||||
|
*/
|
||||||
|
public GHContentUpdateResponse commit() throws IOException {
|
||||||
|
GHContentUpdateResponse response = req.to(repo.getApiTailUrl("contents/" + path), GHContentUpdateResponse.class);
|
||||||
|
|
||||||
|
response.getContent().wrap(repo);
|
||||||
|
response.getCommit().wrapUp(repo);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
20
src/main/java/org/kohsuke/github/GHContentWithLicense.java
Normal file
20
src/main/java/org/kohsuke/github/GHContentWithLicense.java
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link GHContent} with license information.
|
||||||
|
*
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
* @see <a href="https://developer.github.com/v3/licenses/#get-a-repositorys-license">documentation</a>
|
||||||
|
* @see GHRepository#getLicense()
|
||||||
|
*/
|
||||||
|
class GHContentWithLicense extends GHContent {
|
||||||
|
GHLicense license;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
GHContentWithLicense wrap(GHRepository owner) {
|
||||||
|
super.wrap(owner);
|
||||||
|
if (license!=null)
|
||||||
|
license.wrap(owner.root);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,8 +21,8 @@ public class GHCreateRepositoryBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GHCreateRepositoryBuilder description(String description) {
|
public GHCreateRepositoryBuilder description(String description) {
|
||||||
this.builder.with("description",description);
|
this.builder.with("description",description);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GHCreateRepositoryBuilder homepage(URL homepage) {
|
public GHCreateRepositoryBuilder homepage(URL homepage) {
|
||||||
@@ -74,6 +74,30 @@ public class GHCreateRepositoryBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow or disallow squash-merging pull requests.
|
||||||
|
*/
|
||||||
|
public GHCreateRepositoryBuilder allowSquashMerge(boolean b) {
|
||||||
|
this.builder.with("allow_squash_merge",b);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow or disallow merging pull requests with a merge commit.
|
||||||
|
*/
|
||||||
|
public GHCreateRepositoryBuilder allowMergeCommit(boolean b) {
|
||||||
|
this.builder.with("allow_merge_commit",b);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow or disallow rebase-merging pull requests.
|
||||||
|
*/
|
||||||
|
public GHCreateRepositoryBuilder allowRebaseMerge(boolean b) {
|
||||||
|
this.builder.with("allow_rebase_merge",b);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a default .gitignore
|
* Creates a default .gitignore
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
|
||||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class GHDeployKey {
|
public class GHDeployKey {
|
||||||
|
|
||||||
protected String url, key, title;
|
protected String url, key, title;
|
||||||
protected boolean verified;
|
protected boolean verified;
|
||||||
protected int id;
|
protected long id;
|
||||||
private GHRepository owner;
|
private GHRepository owner;
|
||||||
|
|
||||||
public int getId() {
|
public long getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a deployment
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/repos/deployments/">documentation</a>
|
||||||
|
* @see GHRepository#listDeployments(String, String, String, String)
|
||||||
|
* @see GHRepository#getDeployment(long)
|
||||||
|
*/
|
||||||
public class GHDeployment extends GHObject {
|
public class GHDeployment extends GHObject {
|
||||||
private GHRepository owner;
|
private GHRepository owner;
|
||||||
private GitHub root;
|
private GitHub root;
|
||||||
@@ -41,8 +48,8 @@ public class GHDeployment extends GHObject {
|
|||||||
public String getEnvironment() {
|
public String getEnvironment() {
|
||||||
return environment;
|
return environment;
|
||||||
}
|
}
|
||||||
public GHUser getCreator() {
|
public GHUser getCreator() throws IOException {
|
||||||
return creator;
|
return root.intern(creator);
|
||||||
}
|
}
|
||||||
public String getRef() {
|
public String getRef() {
|
||||||
return ref;
|
return ref;
|
||||||
@@ -58,4 +65,17 @@ public class GHDeployment extends GHObject {
|
|||||||
public URL getHtmlUrl() {
|
public URL getHtmlUrl() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GHDeploymentStatusBuilder createStatus(GHDeploymentState state) {
|
||||||
|
return new GHDeploymentStatusBuilder(owner,id,state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PagedIterable<GHDeploymentStatus> listStatuses() {
|
||||||
|
return root.retrieve()
|
||||||
|
.asPagedIterable(
|
||||||
|
statuses_url,
|
||||||
|
GHDeploymentStatus[].class,
|
||||||
|
item -> item.wrap(owner) );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,27 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new deployment status.
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* GHDeployment#createStatus(GHDeploymentState)
|
||||||
|
*/
|
||||||
public class GHDeploymentStatusBuilder {
|
public class GHDeploymentStatusBuilder {
|
||||||
private final Requester builder;
|
private final Requester builder;
|
||||||
private GHRepository repo;
|
private GHRepository repo;
|
||||||
private int deploymentId;
|
private long deploymentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Use {@link GHDeployment#createStatus(GHDeploymentState)}
|
||||||
|
*/
|
||||||
public GHDeploymentStatusBuilder(GHRepository repo, int deploymentId, GHDeploymentState state) {
|
public GHDeploymentStatusBuilder(GHRepository repo, int deploymentId, GHDeploymentState state) {
|
||||||
|
this(repo,(long)deploymentId,state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ GHDeploymentStatusBuilder(GHRepository repo, long deploymentId, GHDeploymentState state) {
|
||||||
this.repo = repo;
|
this.repo = repo;
|
||||||
this.deploymentId = deploymentId;
|
this.deploymentId = deploymentId;
|
||||||
this.builder = new Requester(repo.root);
|
this.builder = new Requester(repo.root);
|
||||||
@@ -26,6 +39,6 @@ public class GHDeploymentStatusBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GHDeploymentStatus create() throws IOException {
|
public GHDeploymentStatus create() throws IOException {
|
||||||
return builder.to(repo.getApiTailUrl("deployments")+"/"+deploymentId+"/statuses",GHDeploymentStatus.class).wrap(repo);
|
return builder.to(repo.getApiTailUrl("deployments/"+deploymentId+"/statuses"),GHDeploymentStatus.class).wrap(repo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,9 @@ import java.util.Locale;
|
|||||||
/**
|
/**
|
||||||
* Hook event type.
|
* Hook event type.
|
||||||
*
|
*
|
||||||
* See http://developer.github.com/v3/events/types/
|
|
||||||
*
|
|
||||||
* @author Kohsuke Kawaguchi
|
* @author Kohsuke Kawaguchi
|
||||||
* @see GHEventInfo
|
* @see GHEventInfo
|
||||||
|
* @see <a href="https://developer.github.com/v3/activity/events/types/">Event type reference</a>
|
||||||
*/
|
*/
|
||||||
public enum GHEvent {
|
public enum GHEvent {
|
||||||
COMMIT_COMMENT,
|
COMMIT_COMMENT,
|
||||||
@@ -22,17 +21,32 @@ public enum GHEvent {
|
|||||||
FORK_APPLY,
|
FORK_APPLY,
|
||||||
GIST,
|
GIST,
|
||||||
GOLLUM,
|
GOLLUM,
|
||||||
|
INSTALLATION,
|
||||||
|
INSTALLATION_REPOSITORIES,
|
||||||
|
INTEGRATION_INSTALLATION_REPOSITORIES,
|
||||||
|
CHECK_SUITE,
|
||||||
ISSUE_COMMENT,
|
ISSUE_COMMENT,
|
||||||
ISSUES,
|
ISSUES,
|
||||||
|
LABEL,
|
||||||
|
MARKETPLACE_PURCHASE,
|
||||||
MEMBER,
|
MEMBER,
|
||||||
|
MEMBERSHIP,
|
||||||
|
MILESTONE,
|
||||||
|
ORGANIZATION,
|
||||||
|
ORG_BLOCK,
|
||||||
PAGE_BUILD,
|
PAGE_BUILD,
|
||||||
|
PROJECT_CARD,
|
||||||
|
PROJECT_COLUMN,
|
||||||
|
PROJECT,
|
||||||
PUBLIC,
|
PUBLIC,
|
||||||
PULL_REQUEST,
|
PULL_REQUEST,
|
||||||
|
PULL_REQUEST_REVIEW,
|
||||||
PULL_REQUEST_REVIEW_COMMENT,
|
PULL_REQUEST_REVIEW_COMMENT,
|
||||||
PUSH,
|
PUSH,
|
||||||
RELEASE,
|
RELEASE,
|
||||||
REPOSITORY, // only valid for org hooks
|
REPOSITORY, // only valid for org hooks
|
||||||
STATUS,
|
STATUS,
|
||||||
|
TEAM,
|
||||||
TEAM_ADD,
|
TEAM_ADD,
|
||||||
WATCH,
|
WATCH,
|
||||||
PING,
|
PING,
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an event.
|
* Represents an event.
|
||||||
*
|
*
|
||||||
@@ -34,7 +34,7 @@ public class GHEventInfo {
|
|||||||
"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" }, justification = "JSON API")
|
"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR" }, justification = "JSON API")
|
||||||
public static class GHEventRepository {
|
public static class GHEventRepository {
|
||||||
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
|
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
|
||||||
private int id;
|
private long id;
|
||||||
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
|
@SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "We don't provide it in API now")
|
||||||
private String url; // repository API URL
|
private String url; // repository API URL
|
||||||
private String name; // owner/repo
|
private String name; // owner/repo
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonSetter;
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -14,11 +17,28 @@ import java.util.List;
|
|||||||
public abstract class GHEventPayload {
|
public abstract class GHEventPayload {
|
||||||
protected GitHub root;
|
protected GitHub root;
|
||||||
|
|
||||||
|
private GHUser sender;
|
||||||
|
|
||||||
/*package*/ GHEventPayload() {
|
/*package*/ GHEventPayload() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the sender or {@code null} if accessed via the events API.
|
||||||
|
* @return the sender or {@code null} if accessed via the events API.
|
||||||
|
*/
|
||||||
|
public GHUser getSender() {
|
||||||
|
return sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSender(GHUser sender) {
|
||||||
|
this.sender = sender;
|
||||||
|
}
|
||||||
|
|
||||||
/*package*/ void wrapUp(GitHub root) {
|
/*package*/ void wrapUp(GitHub root) {
|
||||||
this.root = root;
|
this.root = root;
|
||||||
|
if (sender != null) {
|
||||||
|
sender.wrapUp(root);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,13 +78,147 @@ public abstract class GHEventPayload {
|
|||||||
throw new IllegalStateException("Expected pull_request payload, but got something else. Maybe we've got another type of event?");
|
throw new IllegalStateException("Expected pull_request payload, but got something else. Maybe we've got another type of event?");
|
||||||
if (repository!=null) {
|
if (repository!=null) {
|
||||||
repository.wrap(root);
|
repository.wrap(root);
|
||||||
pull_request.wrap(repository);
|
pull_request.wrapUp(repository);
|
||||||
} else {
|
} else {
|
||||||
pull_request.wrapUp(root);
|
pull_request.wrapUp(root);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A review was added to a pull request
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/activity/events/types/#pullrequestreviewevent">authoritative source</a>
|
||||||
|
*/
|
||||||
|
public static class PullRequestReview extends GHEventPayload {
|
||||||
|
private String action;
|
||||||
|
private GHPullRequestReview review;
|
||||||
|
private GHPullRequest pull_request;
|
||||||
|
private GHRepository repository;
|
||||||
|
|
||||||
|
public String getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHPullRequestReview getReview() {
|
||||||
|
return review;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHPullRequest getPullRequest() {
|
||||||
|
return pull_request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
if (review==null)
|
||||||
|
throw new IllegalStateException("Expected pull_request_review payload, but got something else. Maybe we've got another type of event?");
|
||||||
|
|
||||||
|
review.wrapUp(pull_request);
|
||||||
|
|
||||||
|
if (repository!=null) {
|
||||||
|
repository.wrap(root);
|
||||||
|
pull_request.wrapUp(repository);
|
||||||
|
} else {
|
||||||
|
pull_request.wrapUp(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A review comment was added to a pull request
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/activity/events/types/#pullrequestreviewcommentevent">authoritative source</a>
|
||||||
|
*/
|
||||||
|
public static class PullRequestReviewComment extends GHEventPayload {
|
||||||
|
private String action;
|
||||||
|
private GHPullRequestReviewComment comment;
|
||||||
|
private GHPullRequest pull_request;
|
||||||
|
private GHRepository repository;
|
||||||
|
|
||||||
|
public String getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHPullRequestReviewComment getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHPullRequest getPullRequest() {
|
||||||
|
return pull_request;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
if (comment==null)
|
||||||
|
throw new IllegalStateException("Expected pull_request_review_comment payload, but got something else. Maybe we've got another type of event?");
|
||||||
|
|
||||||
|
comment.wrapUp(pull_request);
|
||||||
|
|
||||||
|
if (repository!=null) {
|
||||||
|
repository.wrap(root);
|
||||||
|
pull_request.wrapUp(repository);
|
||||||
|
} else {
|
||||||
|
pull_request.wrapUp(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Issue has been assigned, unassigned, labeled, unlabeled, opened, edited, milestoned, demilestoned, closed, or reopened.
|
||||||
|
*
|
||||||
|
* @see <a href="http://developer.github.com/v3/activity/events/types/#issueevent">authoritative source</a>
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" },
|
||||||
|
justification = "Constructed by JSON deserialization")
|
||||||
|
public static class Issue extends GHEventPayload {
|
||||||
|
private String action;
|
||||||
|
private GHIssue issue;
|
||||||
|
private GHRepository repository;
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization")
|
||||||
|
public String getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHIssue getIssue() {
|
||||||
|
return issue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIssue(GHIssue issue) {
|
||||||
|
this.issue = issue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepository(GHRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
if (repository != null) {
|
||||||
|
repository.wrap(root);
|
||||||
|
issue.wrap(repository);
|
||||||
|
} else {
|
||||||
|
issue.wrap(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A comment was added to an issue
|
* A comment was added to an issue
|
||||||
*
|
*
|
||||||
@@ -120,17 +274,340 @@ public abstract class GHEventPayload {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A comment was added to a commit
|
||||||
|
*
|
||||||
|
* @see <a href="http://developer.github.com/v3/activity/events/types/#commitcommentevent">authoritative source</a>
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" },
|
||||||
|
justification = "Constructed by JSON deserialization")
|
||||||
|
public static class CommitComment extends GHEventPayload {
|
||||||
|
private String action;
|
||||||
|
private GHCommitComment comment;
|
||||||
|
private GHRepository repository;
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization")
|
||||||
|
public String getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommitComment getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setComment(GHCommitComment comment) {
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepository(GHRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
if (repository != null) {
|
||||||
|
repository.wrap(root);
|
||||||
|
comment.wrap(repository);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A repository, branch, or tag was created
|
||||||
|
*
|
||||||
|
* @see <a href="http://developer.github.com/v3/activity/events/types/#createevent">authoritative source</a>
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" },
|
||||||
|
justification = "Constructed by JSON deserialization")
|
||||||
|
public static class Create extends GHEventPayload {
|
||||||
|
private String ref;
|
||||||
|
@JsonProperty("ref_type")
|
||||||
|
private String refType;
|
||||||
|
@JsonProperty("master_branch")
|
||||||
|
private String masterBranch;
|
||||||
|
private String description;
|
||||||
|
private GHRepository repository;
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization")
|
||||||
|
public String getRef() {
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization")
|
||||||
|
public String getRefType() {
|
||||||
|
return refType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization")
|
||||||
|
public String getMasterBranch() {
|
||||||
|
return masterBranch;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization")
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepository(GHRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
if (repository != null) {
|
||||||
|
repository.wrap(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A branch, or tag was deleted
|
||||||
|
*
|
||||||
|
* @see <a href="http://developer.github.com/v3/activity/events/types/#deleteevent">authoritative source</a>
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" },
|
||||||
|
justification = "Constructed by JSON deserialization")
|
||||||
|
public static class Delete extends GHEventPayload {
|
||||||
|
private String ref;
|
||||||
|
@JsonProperty("ref_type")
|
||||||
|
private String refType;
|
||||||
|
private GHRepository repository;
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization")
|
||||||
|
public String getRef() {
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization")
|
||||||
|
public String getRefType() {
|
||||||
|
return refType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepository(GHRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
if (repository != null) {
|
||||||
|
repository.wrap(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A deployment
|
||||||
|
*
|
||||||
|
* @see <a href="http://developer.github.com/v3/activity/events/types/#deploymentevent">authoritative source</a>
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" },
|
||||||
|
justification = "Constructed by JSON deserialization")
|
||||||
|
public static class Deployment extends GHEventPayload {
|
||||||
|
private GHDeployment deployment;
|
||||||
|
private GHRepository repository;
|
||||||
|
|
||||||
|
public GHDeployment getDeployment() {
|
||||||
|
return deployment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeployment(GHDeployment deployment) {
|
||||||
|
this.deployment = deployment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepository(GHRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
if (repository != null) {
|
||||||
|
repository.wrap(root);
|
||||||
|
deployment.wrap(repository);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A deployment
|
||||||
|
*
|
||||||
|
* @see <a href="http://developer.github.com/v3/activity/events/types/#deploymentstatusevent">authoritative source</a>
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" },
|
||||||
|
justification = "Constructed by JSON deserialization")
|
||||||
|
public static class DeploymentStatus extends GHEventPayload {
|
||||||
|
@JsonProperty("deployment_status")
|
||||||
|
private GHDeploymentStatus deploymentStatus;
|
||||||
|
private GHDeployment deployment;
|
||||||
|
private GHRepository repository;
|
||||||
|
|
||||||
|
public GHDeploymentStatus getDeploymentStatus() {
|
||||||
|
return deploymentStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeploymentStatus(GHDeploymentStatus deploymentStatus) {
|
||||||
|
this.deploymentStatus = deploymentStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHDeployment getDeployment() {
|
||||||
|
return deployment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeployment(GHDeployment deployment) {
|
||||||
|
this.deployment = deployment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepository(GHRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
if (repository != null) {
|
||||||
|
repository.wrap(root);
|
||||||
|
deployment.wrap(repository);
|
||||||
|
deploymentStatus.wrap(repository);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A user forked a repository
|
||||||
|
*
|
||||||
|
* @see <a href="http://developer.github.com/v3/activity/events/types/#forkevent">authoritative source</a>
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" },
|
||||||
|
justification = "Constructed by JSON deserialization")
|
||||||
|
public static class Fork extends GHEventPayload {
|
||||||
|
private GHRepository forkee;
|
||||||
|
private GHRepository repository;
|
||||||
|
|
||||||
|
|
||||||
|
public GHRepository getForkee() {
|
||||||
|
return forkee;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setForkee(GHRepository forkee) {
|
||||||
|
this.forkee = forkee;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepository(GHRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
forkee.wrap(root);
|
||||||
|
if (repository != null) {
|
||||||
|
repository.wrap(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A ping.
|
||||||
|
*/
|
||||||
|
public static class Ping extends GHEventPayload {
|
||||||
|
private GHRepository repository;
|
||||||
|
private GHOrganization organization;
|
||||||
|
|
||||||
|
public void setRepository(GHRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHOrganization getOrganization() {
|
||||||
|
return organization;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrganization(GHOrganization organization) {
|
||||||
|
this.organization = organization;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
if (repository!=null)
|
||||||
|
repository.wrap(root);
|
||||||
|
if (organization != null) {
|
||||||
|
organization.wrapUp(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A repository was made public.
|
||||||
|
*
|
||||||
|
* @see <a href="http://developer.github.com/v3/activity/events/types/#publicevent">authoritative source</a>
|
||||||
|
*/
|
||||||
|
public static class Public extends GHEventPayload {
|
||||||
|
private GHRepository repository;
|
||||||
|
|
||||||
|
public void setRepository(GHRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
if (repository!=null)
|
||||||
|
repository.wrap(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A commit was pushed.
|
* A commit was pushed.
|
||||||
*
|
*
|
||||||
* @see <a href="http://developer.github.com/v3/activity/events/types/#pushevent">authoritative source</a>
|
* @see <a href="http://developer.github.com/v3/activity/events/types/#pushevent">authoritative source</a>
|
||||||
*/
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD", "UUF_UNUSED_FIELD"},
|
||||||
|
justification = "Constructed by JSON deserialization")
|
||||||
public static class Push extends GHEventPayload {
|
public static class Push extends GHEventPayload {
|
||||||
private String head, before;
|
private String head, before;
|
||||||
|
private boolean created, deleted, forced;
|
||||||
private String ref;
|
private String ref;
|
||||||
private int size;
|
private int size;
|
||||||
private List<PushCommit> commits;
|
private List<PushCommit> commits;
|
||||||
private GHRepository repository;
|
private GHRepository repository;
|
||||||
|
private Pusher pusher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SHA of the HEAD commit on the repository
|
* The SHA of the HEAD commit on the repository
|
||||||
@@ -147,6 +624,11 @@ public abstract class GHEventPayload {
|
|||||||
return before;
|
return before;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonSetter // alias
|
||||||
|
private void setAfter(String after) {
|
||||||
|
head = after;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The full Git ref that was pushed. Example: “refs/heads/master”
|
* The full Git ref that was pushed. Example: “refs/heads/master”
|
||||||
*/
|
*/
|
||||||
@@ -162,6 +644,18 @@ public abstract class GHEventPayload {
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isCreated() {
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDeleted() {
|
||||||
|
return deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isForced() {
|
||||||
|
return forced;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of pushed commits.
|
* The list of pushed commits.
|
||||||
*/
|
*/
|
||||||
@@ -173,6 +667,14 @@ public abstract class GHEventPayload {
|
|||||||
return repository;
|
return repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Pusher getPusher() {
|
||||||
|
return pusher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPusher(Pusher pusher) {
|
||||||
|
this.pusher = pusher;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void wrapUp(GitHub root) {
|
void wrapUp(GitHub root) {
|
||||||
super.wrapUp(root);
|
super.wrapUp(root);
|
||||||
@@ -180,18 +682,44 @@ public abstract class GHEventPayload {
|
|||||||
repository.wrap(root);
|
repository.wrap(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Pusher {
|
||||||
|
private String name, email;
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commit in a push
|
* Commit in a push
|
||||||
*/
|
*/
|
||||||
public static class PushCommit {
|
public static class PushCommit {
|
||||||
private GitUser author;
|
private GitUser author;
|
||||||
|
private GitUser committer;
|
||||||
private String url, sha, message;
|
private String url, sha, message;
|
||||||
private boolean distinct;
|
private boolean distinct;
|
||||||
|
private List<String> added, removed, modified;
|
||||||
|
|
||||||
public GitUser getAuthor() {
|
public GitUser getAuthor() {
|
||||||
return author;
|
return author;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GitUser getCommitter() {
|
||||||
|
return committer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Points to the commit API resource.
|
* Points to the commit API resource.
|
||||||
*/
|
*/
|
||||||
@@ -203,6 +731,11 @@ public abstract class GHEventPayload {
|
|||||||
return sha;
|
return sha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@JsonSetter
|
||||||
|
private void setId(String id) {
|
||||||
|
sha = id;
|
||||||
|
}
|
||||||
|
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
@@ -213,6 +746,103 @@ public abstract class GHEventPayload {
|
|||||||
public boolean isDistinct() {
|
public boolean isDistinct() {
|
||||||
return distinct;
|
return distinct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getAdded() {
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getRemoved() {
|
||||||
|
return removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getModified() {
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A release was added to the repo
|
||||||
|
*
|
||||||
|
* @see <a href="http://developer.github.com/v3/activity/events/types/#releaseevent">authoritative source</a>
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD" },
|
||||||
|
justification = "Constructed by JSON deserialization")
|
||||||
|
public static class Release extends GHEventPayload {
|
||||||
|
private String action;
|
||||||
|
private GHRelease release;
|
||||||
|
private GHRepository repository;
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = "UWF_UNWRITTEN_FIELD", justification = "Comes from JSON deserialization")
|
||||||
|
public String getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRelease getRelease() {
|
||||||
|
return release;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRelease(GHRelease release) {
|
||||||
|
this.release = release;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepository(GHRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
if (repository != null) {
|
||||||
|
repository.wrap(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A repository was created, deleted, made public, or made private.
|
||||||
|
*
|
||||||
|
* @see <a href="http://developer.github.com/v3/activity/events/types/#repositoryevent">authoritative source</a>
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", "NP_UNWRITTEN_FIELD", "UWF_UNWRITTEN_FIELD"},
|
||||||
|
justification = "Constructed by JSON deserialization")
|
||||||
|
public static class Repository extends GHEventPayload {
|
||||||
|
private String action;
|
||||||
|
private GHRepository repository;
|
||||||
|
private GHOrganization organization;
|
||||||
|
|
||||||
|
public String getAction() {
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRepository(GHRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHOrganization getOrganization() {
|
||||||
|
return organization;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrganization(GHOrganization organization) {
|
||||||
|
this.organization = organization;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
repository.wrap(root);
|
||||||
|
if (organization != null) {
|
||||||
|
organization.wrapUp(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import javax.annotation.CheckForNull;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request/responce contains useful metadata.
|
||||||
|
* Custom exception allows store info for next diagnostics.
|
||||||
|
*
|
||||||
|
* @author Kanstantsin Shautsou
|
||||||
|
*/
|
||||||
|
public class GHFileNotFoundException extends FileNotFoundException {
|
||||||
|
protected Map<String, List<String>> responseHeaderFields;
|
||||||
|
|
||||||
|
public GHFileNotFoundException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHFileNotFoundException(String s) {
|
||||||
|
super(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
@CheckForNull
|
||||||
|
public Map<String, List<String>> getResponseHeaderFields() {
|
||||||
|
return responseHeaderFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHFileNotFoundException withResponseHeaderFields(HttpURLConnection urlConnection) {
|
||||||
|
this.responseHeaderFields = urlConnection.getHeaderFields();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@@ -38,8 +39,8 @@ public class GHGist extends GHObject {
|
|||||||
/**
|
/**
|
||||||
* User that owns this Gist.
|
* User that owns this Gist.
|
||||||
*/
|
*/
|
||||||
public GHUser getOwner() {
|
public GHUser getOwner() throws IOException {
|
||||||
return owner;
|
return root.intern(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getForksUrl() {
|
public String getForksUrl() {
|
||||||
@@ -103,7 +104,7 @@ public class GHGist extends GHObject {
|
|||||||
* Used when caller obtains {@link GHGist} without knowing its owner.
|
* Used when caller obtains {@link GHGist} without knowing its owner.
|
||||||
* A partially constructed owner object is interned.
|
* A partially constructed owner object is interned.
|
||||||
*/
|
*/
|
||||||
/*package*/ GHGist wrapUp(GitHub root) throws IOException {
|
/*package*/ GHGist wrapUp(GitHub root) {
|
||||||
this.owner = root.getUser(owner);
|
this.owner = root.getUser(owner);
|
||||||
this.root = root;
|
this.root = root;
|
||||||
wrapUp();
|
wrapUp();
|
||||||
@@ -115,8 +116,13 @@ public class GHGist extends GHObject {
|
|||||||
e.getValue().fileName = e.getKey();
|
e.getValue().fileName = e.getKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String getApiTailUrl(String tail) {
|
String getApiTailUrl(String tail) {
|
||||||
return "/gists/" + id + '/' + tail;
|
String result = "/gists/" + id;
|
||||||
|
if (!StringUtils.isBlank(tail)) {
|
||||||
|
result += StringUtils.prependIfMissing(tail, "/");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void star() throws IOException {
|
public void star() throws IOException {
|
||||||
@@ -139,21 +145,11 @@ public class GHGist extends GHObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PagedIterable<GHGist> listForks() {
|
public PagedIterable<GHGist> listForks() {
|
||||||
return new PagedIterable<GHGist>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHGist> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHGist>(root.retrieve().asIterator(getApiTailUrl("forks"), GHGist[].class, pageSize)) {
|
getApiTailUrl("forks"),
|
||||||
@Override
|
GHGist[].class,
|
||||||
protected void wrapUp(GHGist[] page) {
|
item -> item.wrapUp(root) );
|
||||||
try {
|
|
||||||
for (GHGist c : page)
|
|
||||||
c.wrapUp(root);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new Error(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,6 +159,13 @@ public class GHGist extends GHObject {
|
|||||||
new Requester(root).method("DELETE").to("/gists/" + id);
|
new Requester(root).method("DELETE").to("/gists/" + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates this gist via a builder.
|
||||||
|
*/
|
||||||
|
public GHGistUpdater update() throws IOException {
|
||||||
|
return new GHGistUpdater(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object o) {
|
public boolean equals(Object o) {
|
||||||
if (this == o) return true;
|
if (this == o) return true;
|
||||||
@@ -176,4 +179,10 @@ public class GHGist extends GHObject {
|
|||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return id.hashCode();
|
return id.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GHGist wrap(GHUser owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
this.root = owner.root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
60
src/main/java/org/kohsuke/github/GHGistUpdater.java
Normal file
60
src/main/java/org/kohsuke/github/GHGistUpdater.java
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder pattern for updating a Gist.
|
||||||
|
*
|
||||||
|
* @author Martin van Zijl
|
||||||
|
*/
|
||||||
|
public class GHGistUpdater {
|
||||||
|
private final GHGist base;
|
||||||
|
private final Requester builder;
|
||||||
|
LinkedHashMap<String,Object> files;
|
||||||
|
|
||||||
|
GHGistUpdater(GHGist base) {
|
||||||
|
this.base = base;
|
||||||
|
this.builder = new Requester(base.root);
|
||||||
|
|
||||||
|
files = new LinkedHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHGistUpdater addFile(String fileName, String content) throws IOException {
|
||||||
|
updateFile(fileName, content);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // This method does not work.
|
||||||
|
// public GHGistUpdater deleteFile(String fileName) throws IOException {
|
||||||
|
// files.put(fileName, Collections.singletonMap("filename", null));
|
||||||
|
// return this;
|
||||||
|
// }
|
||||||
|
|
||||||
|
public GHGistUpdater renameFile(String fileName, String newFileName) throws IOException
|
||||||
|
{
|
||||||
|
files.put(fileName, Collections.singletonMap("filename", newFileName));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHGistUpdater updateFile(String fileName, String content) throws IOException {
|
||||||
|
files.put(fileName, Collections.singletonMap("content", content));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHGistUpdater description(String desc) {
|
||||||
|
builder.with("description",desc);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the Gist based on the parameters specified thus far.
|
||||||
|
*/
|
||||||
|
public GHGist update() throws IOException {
|
||||||
|
builder._with("files", files);
|
||||||
|
return builder
|
||||||
|
.method("PATCH")
|
||||||
|
.to(base.getApiTailUrl(""), GHGist.class).wrap(base.owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -41,6 +42,13 @@ public abstract class GHHook extends GHObject {
|
|||||||
return Collections.unmodifiableMap(config);
|
return Collections.unmodifiableMap(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see <a href="https://developer.github.com/v3/repos/hooks/#ping-a-hook">Ping hook</a>
|
||||||
|
*/
|
||||||
|
public void ping() throws IOException {
|
||||||
|
new Requester(getRoot()).method("POST").to(getApiRoute() + "/pings");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes this hook.
|
* Deletes this hook.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
34
src/main/java/org/kohsuke/github/GHIOException.java
Normal file
34
src/main/java/org/kohsuke/github/GHIOException.java
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import javax.annotation.CheckForNull;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request/responce contains useful metadata.
|
||||||
|
* Custom exception allows store info for next diagnostics.
|
||||||
|
*
|
||||||
|
* @author Kanstantsin Shautsou
|
||||||
|
*/
|
||||||
|
public class GHIOException extends IOException {
|
||||||
|
protected Map<String, List<String>> responseHeaderFields;
|
||||||
|
|
||||||
|
public GHIOException() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHIOException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@CheckForNull
|
||||||
|
public Map<String, List<String>> getResponseHeaderFields() {
|
||||||
|
return responseHeaderFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHIOException withResponseHeaderFields(HttpURLConnection urlConnection) {
|
||||||
|
this.responseHeaderFields = urlConnection.getHeaderFields();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/main/java/org/kohsuke/github/GHInvitation.java
Normal file
46
src/main/java/org/kohsuke/github/GHInvitation.java
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see GitHub#getMyInvitations()
|
||||||
|
* @see GHRepository#listInvitations()
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
|
||||||
|
"NP_UNWRITTEN_FIELD", "UUF_UNUSED_FIELD"}, justification = "JSON API")
|
||||||
|
public class GHInvitation extends GHObject {
|
||||||
|
/*package almost final*/ GitHub root;
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
private GHRepository repository;
|
||||||
|
private GHUser invitee, inviter;
|
||||||
|
private String permissions;
|
||||||
|
private String html_url;
|
||||||
|
|
||||||
|
/*package*/ GHInvitation wrapUp(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept a repository invitation.
|
||||||
|
*/
|
||||||
|
public void accept() throws IOException {
|
||||||
|
root.retrieve().method("PATCH").to("/user/repository_invitations/" + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decline a repository invitation.
|
||||||
|
*/
|
||||||
|
public void decline() throws IOException {
|
||||||
|
root.retrieve().method("DELETE").to("/user/repository_invitations/" + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL getHtmlUrl() {
|
||||||
|
return GitHub.parseURL(html_url);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -24,16 +24,21 @@
|
|||||||
|
|
||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.SQUIRREL_GIRL;
|
||||||
|
|
||||||
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an issue on GitHub.
|
* Represents an issue on GitHub.
|
||||||
@@ -44,16 +49,20 @@ import java.util.Locale;
|
|||||||
* @see GitHub#searchIssues()
|
* @see GitHub#searchIssues()
|
||||||
* @see GHIssueSearchBuilder
|
* @see GHIssueSearchBuilder
|
||||||
*/
|
*/
|
||||||
public class GHIssue extends GHObject {
|
public class GHIssue extends GHObject implements Reactable{
|
||||||
|
private static final String ASSIGNEES = "assignees";
|
||||||
|
|
||||||
GitHub root;
|
GitHub root;
|
||||||
GHRepository owner;
|
GHRepository owner;
|
||||||
|
|
||||||
// API v3
|
// API v3
|
||||||
protected GHUser assignee;
|
protected GHUser assignee; // not sure what this field is now that 'assignees' exist
|
||||||
|
protected GHUser[] assignees;
|
||||||
protected String state;
|
protected String state;
|
||||||
protected int number;
|
protected int number;
|
||||||
protected String closed_at;
|
protected String closed_at;
|
||||||
protected int comments;
|
protected int comments;
|
||||||
|
@SkipFromToString
|
||||||
protected String body;
|
protected String body;
|
||||||
// for backward compatibility with < 1.63, this collection needs to hold instances of Label, not GHLabel
|
// for backward compatibility with < 1.63, this collection needs to hold instances of Label, not GHLabel
|
||||||
protected List<Label> labels;
|
protected List<Label> labels;
|
||||||
@@ -62,6 +71,7 @@ public class GHIssue extends GHObject {
|
|||||||
protected GHIssue.PullRequest pull_request;
|
protected GHIssue.PullRequest pull_request;
|
||||||
protected GHMilestone milestone;
|
protected GHMilestone milestone;
|
||||||
protected GHUser closed_by;
|
protected GHUser closed_by;
|
||||||
|
protected boolean locked;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use {@link GHLabel}
|
* @deprecated use {@link GHLabel}
|
||||||
@@ -78,6 +88,7 @@ public class GHIssue extends GHObject {
|
|||||||
/*package*/ GHIssue wrap(GitHub root) {
|
/*package*/ GHIssue wrap(GitHub root) {
|
||||||
this.root = root;
|
this.root = root;
|
||||||
if(assignee != null) assignee.wrapUp(root);
|
if(assignee != null) assignee.wrapUp(root);
|
||||||
|
if(assignees!=null) GHUser.wrap(assignees,root);
|
||||||
if(user != null) user.wrapUp(root);
|
if(user != null) user.wrapUp(root);
|
||||||
if(closed_by != null) closed_by.wrapUp(root);
|
if(closed_by != null) closed_by.wrapUp(root);
|
||||||
return this;
|
return this;
|
||||||
@@ -122,6 +133,10 @@ public class GHIssue extends GHObject {
|
|||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLocked() {
|
||||||
|
return locked;
|
||||||
|
}
|
||||||
|
|
||||||
public GHIssueState getState() {
|
public GHIssueState getState() {
|
||||||
return Enum.valueOf(GHIssueState.class, state.toUpperCase(Locale.ENGLISH));
|
return Enum.valueOf(GHIssueState.class, state.toUpperCase(Locale.ENGLISH));
|
||||||
}
|
}
|
||||||
@@ -141,6 +156,14 @@ public class GHIssue extends GHObject {
|
|||||||
return GitHub.parseURL(url);
|
return GitHub.parseURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void lock() throws IOException {
|
||||||
|
new Requester(root).method("PUT").to(getApiRoute()+"/lock");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unlock() throws IOException {
|
||||||
|
new Requester(root).method("PUT").to(getApiRoute()+"/lock");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the issue by adding a comment.
|
* Updates the issue by adding a comment.
|
||||||
*
|
*
|
||||||
@@ -183,14 +206,79 @@ public class GHIssue extends GHObject {
|
|||||||
edit("body",body);
|
edit("body",body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMilestone(GHMilestone milestone) throws IOException {
|
||||||
|
edit("milestone",milestone.getNumber());
|
||||||
|
}
|
||||||
|
|
||||||
public void assignTo(GHUser user) throws IOException {
|
public void assignTo(GHUser user) throws IOException {
|
||||||
editIssue("assignee", user.getLogin());
|
setAssignees(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLabels(String... labels) throws IOException {
|
public void setLabels(String... labels) throws IOException {
|
||||||
editIssue("labels",labels);
|
editIssue("labels",labels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds labels to the issue.
|
||||||
|
*
|
||||||
|
* @param names Names of the label
|
||||||
|
*/
|
||||||
|
public void addLabels(String... names) throws IOException {
|
||||||
|
_addLabels(Arrays.asList(names));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLabels(GHLabel... labels) throws IOException {
|
||||||
|
addLabels(Arrays.asList(labels));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLabels(Collection<GHLabel> labels) throws IOException {
|
||||||
|
_addLabels(GHLabel.toNames(labels));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void _addLabels(Collection<String> names) throws IOException {
|
||||||
|
List<String> newLabels = new ArrayList<String>();
|
||||||
|
|
||||||
|
for (GHLabel label : getLabels()) {
|
||||||
|
newLabels.add(label.getName());
|
||||||
|
}
|
||||||
|
for (String name : names) {
|
||||||
|
if (!newLabels.contains(name)) {
|
||||||
|
newLabels.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setLabels(newLabels.toArray(new String[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a given label by name from this issue.
|
||||||
|
*/
|
||||||
|
public void removeLabels(String... names) throws IOException {
|
||||||
|
_removeLabels(Arrays.asList(names));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #removeLabels(String...)
|
||||||
|
*/
|
||||||
|
public void removeLabels(GHLabel... labels) throws IOException {
|
||||||
|
removeLabels(Arrays.asList(labels));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeLabels(Collection<GHLabel> labels) throws IOException {
|
||||||
|
_removeLabels(GHLabel.toNames(labels));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void _removeLabels(Collection<String> names) throws IOException {
|
||||||
|
List<String> newLabels = new ArrayList<String>();
|
||||||
|
|
||||||
|
for (GHLabel l : getLabels()) {
|
||||||
|
if (!names.contains(l.getName())) {
|
||||||
|
newLabels.add(l.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setLabels(newLabels.toArray(new String[0]));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains all the comments associated with this issue.
|
* Obtains all the comments associated with this issue.
|
||||||
*
|
*
|
||||||
@@ -204,16 +292,52 @@ public class GHIssue extends GHObject {
|
|||||||
* Obtains all the comments associated with this issue.
|
* Obtains all the comments associated with this issue.
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHIssueComment> listComments() throws IOException {
|
public PagedIterable<GHIssueComment> listComments() throws IOException {
|
||||||
return new PagedIterable<GHIssueComment>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHIssueComment> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHIssueComment>(root.retrieve().asIterator(getIssuesApiRoute() + "/comments", GHIssueComment[].class, pageSize)) {
|
getIssuesApiRoute() + "/comments",
|
||||||
protected void wrapUp(GHIssueComment[] page) {
|
GHIssueComment[].class,
|
||||||
for (GHIssueComment c : page)
|
item -> item.wrapUp(GHIssue.this) );
|
||||||
c.wrapUp(GHIssue.this);
|
}
|
||||||
}
|
|
||||||
};
|
@Preview @Deprecated
|
||||||
}
|
public GHReaction createReaction(ReactionContent content) throws IOException {
|
||||||
};
|
return new Requester(owner.root)
|
||||||
|
.withPreview(SQUIRREL_GIRL)
|
||||||
|
.with("content", content.getContent())
|
||||||
|
.to(getApiRoute()+"/reactions", GHReaction.class).wrap(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview @Deprecated
|
||||||
|
public PagedIterable<GHReaction> listReactions() {
|
||||||
|
return owner.root.retrieve().withPreview(SQUIRREL_GIRL)
|
||||||
|
.asPagedIterable(
|
||||||
|
getApiRoute()+"/reactions",
|
||||||
|
GHReaction[].class,
|
||||||
|
item -> item.wrap(owner.root) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAssignees(GHUser... assignees) throws IOException {
|
||||||
|
addAssignees(Arrays.asList(assignees));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAssignees(Collection<GHUser> assignees) throws IOException {
|
||||||
|
root.retrieve().method("POST").withLogins(ASSIGNEES,assignees).to(getIssuesApiRoute()+"/assignees",this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssignees(GHUser... assignees) throws IOException {
|
||||||
|
setAssignees(Arrays.asList(assignees));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAssignees(Collection<GHUser> assignees) throws IOException {
|
||||||
|
new Requester(root).withLogins(ASSIGNEES, assignees).method("PATCH").to(getIssuesApiRoute());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAssignees(GHUser... assignees) throws IOException {
|
||||||
|
removeAssignees(Arrays.asList(assignees));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAssignees(Collection<GHUser> assignees) throws IOException {
|
||||||
|
root.retrieve().method("DELETE").withLogins(ASSIGNEES,assignees).inBody().to(getIssuesApiRoute()+"/assignees",this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getApiRoute() {
|
protected String getApiRoute() {
|
||||||
@@ -224,15 +348,19 @@ public class GHIssue extends GHObject {
|
|||||||
return "/repos/"+owner.getOwnerName()+"/"+owner.getName()+"/issues/"+number;
|
return "/repos/"+owner.getOwnerName()+"/"+owner.getName()+"/issues/"+number;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GHUser getAssignee() {
|
public GHUser getAssignee() throws IOException {
|
||||||
return assignee;
|
return root.intern(assignee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<GHUser> getAssignees() {
|
||||||
|
return Collections.unmodifiableList(Arrays.asList(assignees));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User who submitted the issue.
|
* User who submitted the issue.
|
||||||
*/
|
*/
|
||||||
public GHUser getUser() {
|
public GHUser getUser() throws IOException {
|
||||||
return user;
|
return root.intern(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -243,12 +371,16 @@ public class GHIssue extends GHObject {
|
|||||||
* even for an issue that's already closed. See
|
* even for an issue that's already closed. See
|
||||||
* https://github.com/kohsuke/github-api/issues/60.
|
* https://github.com/kohsuke/github-api/issues/60.
|
||||||
*/
|
*/
|
||||||
public GHUser getClosedBy() {
|
public GHUser getClosedBy() throws IOException {
|
||||||
if(!"closed".equals(state)) return null;
|
if(!"closed".equals(state)) return null;
|
||||||
if(closed_by != null) return closed_by;
|
|
||||||
|
//TODO
|
||||||
//TODO closed_by = owner.getIssue(number).getClosed_by();
|
/*
|
||||||
return closed_by;
|
if (closed_by==null) {
|
||||||
|
closed_by = owner.getIssue(number).getClosed_by();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
return root.intern(closed_by);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCommentsCount(){
|
public int getCommentsCount(){
|
||||||
@@ -287,4 +419,15 @@ public class GHIssue extends GHObject {
|
|||||||
return GitHub.parseURL(html_url);
|
return GitHub.parseURL(html_url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists events for this issue.
|
||||||
|
* See https://developer.github.com/v3/issues/events/
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHIssueEvent> listEvents() throws IOException {
|
||||||
|
return root.retrieve().asPagedIterable(
|
||||||
|
owner.getApiTailUrl(String.format("/issues/%s/events", number)),
|
||||||
|
GHIssueEvent[].class,
|
||||||
|
item -> item.wrapUp(GHIssue.this) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public class GHIssueBuilder {
|
|||||||
private final GHRepository repo;
|
private final GHRepository repo;
|
||||||
private final Requester builder;
|
private final Requester builder;
|
||||||
private List<String> labels = new ArrayList<String>();
|
private List<String> labels = new ArrayList<String>();
|
||||||
|
private List<String> assignees = new ArrayList<String>();
|
||||||
|
|
||||||
GHIssueBuilder(GHRepository repo, String title) {
|
GHIssueBuilder(GHRepository repo, String title) {
|
||||||
this.repo = repo;
|
this.repo = repo;
|
||||||
@@ -28,13 +29,13 @@ public class GHIssueBuilder {
|
|||||||
|
|
||||||
public GHIssueBuilder assignee(GHUser user) {
|
public GHIssueBuilder assignee(GHUser user) {
|
||||||
if (user!=null)
|
if (user!=null)
|
||||||
builder.with("assignee",user.getLogin());
|
assignees.add(user.getLogin());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GHIssueBuilder assignee(String user) {
|
public GHIssueBuilder assignee(String user) {
|
||||||
if (user!=null)
|
if (user!=null)
|
||||||
builder.with("assignee",user);
|
assignees.add(user);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +55,6 @@ public class GHIssueBuilder {
|
|||||||
* Creates a new issue.
|
* Creates a new issue.
|
||||||
*/
|
*/
|
||||||
public GHIssue create() throws IOException {
|
public GHIssue create() throws IOException {
|
||||||
return builder.with("labels",labels).to(repo.getApiTailUrl("issues"),GHIssue.class).wrap(repo);
|
return builder.with("labels",labels).with("assignees",assignees).to(repo.getApiTailUrl("issues"),GHIssue.class).wrap(repo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,16 +26,20 @@ package org.kohsuke.github;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Comment to the issue
|
* Comment to the issue
|
||||||
*
|
*
|
||||||
* @author Kohsuke Kawaguchi
|
* @author Kohsuke Kawaguchi
|
||||||
|
* @see GHIssue#comment(String)
|
||||||
|
* @see GHIssue#listComments()
|
||||||
*/
|
*/
|
||||||
public class GHIssueComment extends GHObject {
|
public class GHIssueComment extends GHObject implements Reactable {
|
||||||
GHIssue owner;
|
GHIssue owner;
|
||||||
|
|
||||||
private String body, gravatar_id;
|
private String body, gravatar_id, html_url, author_association;
|
||||||
private GHUser user;
|
private GHUser user; // not fully populated. beware.
|
||||||
|
|
||||||
/*package*/ GHIssueComment wrapUp(GHIssue owner) {
|
/*package*/ GHIssueComment wrapUp(GHIssue owner) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
@@ -68,15 +72,16 @@ public class GHIssueComment extends GHObject {
|
|||||||
* Gets the user who posted this comment.
|
* Gets the user who posted this comment.
|
||||||
*/
|
*/
|
||||||
public GHUser getUser() throws IOException {
|
public GHUser getUser() throws IOException {
|
||||||
return owner.root.getUser(user.getLogin());
|
return owner == null || owner.root.isOffline() ? user : owner.root.getUser(user.getLogin());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated This object has no HTML URL.
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public URL getHtmlUrl() {
|
public URL getHtmlUrl() {
|
||||||
return null;
|
return GitHub.parseURL(html_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHCommentAuthorAssociation getAuthorAssociation() {
|
||||||
|
return GHCommentAuthorAssociation.valueOf(author_association);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,7 +98,25 @@ public class GHIssueComment extends GHObject {
|
|||||||
public void delete() throws IOException {
|
public void delete() throws IOException {
|
||||||
new Requester(owner.root).method("DELETE").to(getApiRoute());
|
new Requester(owner.root).method("DELETE").to(getApiRoute());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHReaction createReaction(ReactionContent content) throws IOException {
|
||||||
|
return new Requester(owner.root)
|
||||||
|
.withPreview(SQUIRREL_GIRL)
|
||||||
|
.with("content", content.getContent())
|
||||||
|
.to(getApiRoute()+"/reactions", GHReaction.class).wrap(owner.root);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview @Deprecated
|
||||||
|
public PagedIterable<GHReaction> listReactions() {
|
||||||
|
return owner.root.retrieve()
|
||||||
|
.withPreview(SQUIRREL_GIRL)
|
||||||
|
.asPagedIterable(
|
||||||
|
getApiRoute()+"/reactions",
|
||||||
|
GHReaction[].class,
|
||||||
|
item -> item.wrap(owner.root) );
|
||||||
|
}
|
||||||
|
|
||||||
private String getApiRoute() {
|
private String getApiRoute() {
|
||||||
return "/repos/"+owner.getRepository().getOwnerName()+"/"+owner.getRepository().getName()+"/issues/comments/" + id;
|
return "/repos/"+owner.getRepository().getOwnerName()+"/"+owner.getRepository().getName()+"/issues/comments/" + id;
|
||||||
}
|
}
|
||||||
|
|||||||
81
src/main/java/org/kohsuke/github/GHIssueEvent.java
Normal file
81
src/main/java/org/kohsuke/github/GHIssueEvent.java
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Martin van Zijl
|
||||||
|
*/
|
||||||
|
public class GHIssueEvent {
|
||||||
|
private GitHub root;
|
||||||
|
|
||||||
|
private long id;
|
||||||
|
private String node_id;
|
||||||
|
private String url;
|
||||||
|
private GHUser actor;
|
||||||
|
private String event;
|
||||||
|
private String commit_id;
|
||||||
|
private String commit_url;
|
||||||
|
private String created_at;
|
||||||
|
|
||||||
|
private GHIssue issue;
|
||||||
|
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNodeId() {
|
||||||
|
return node_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHUser getActor() {
|
||||||
|
return actor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEvent() {
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCommitId() {
|
||||||
|
return commit_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCommitUrl() {
|
||||||
|
return commit_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreatedAt() {
|
||||||
|
return GitHub.parseDate(created_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitHub getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHIssue getIssue() {
|
||||||
|
return issue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHIssueEvent wrapUp(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
GHIssueEvent wrapUp(GHIssue parent) {
|
||||||
|
this.issue = parent;
|
||||||
|
this.root = parent.root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("Issue %d was %s by %s on %s",
|
||||||
|
getIssue().getNumber(),
|
||||||
|
getEvent(),
|
||||||
|
getActor().getLogin(),
|
||||||
|
getCreatedAt().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search issues.
|
* Search issues.
|
||||||
*
|
*
|
||||||
@@ -41,6 +39,11 @@ public class GHIssueSearchBuilder extends GHSearchBuilder<GHIssue> {
|
|||||||
return q("is:merged");
|
return q("is:merged");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GHIssueSearchBuilder order(GHDirection v) {
|
||||||
|
req.with("order",v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public GHIssueSearchBuilder sort(Sort sort) {
|
public GHIssueSearchBuilder sort(Sort sort) {
|
||||||
req.with("sort",sort);
|
req.with("sort",sort);
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
import org.apache.commons.lang.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SSH public key.
|
* SSH public key.
|
||||||
|
|||||||
@@ -1,14 +1,19 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.SYMMETRA;
|
||||||
/**
|
/**
|
||||||
* @author Kohsuke Kawaguchi
|
* @author Kohsuke Kawaguchi
|
||||||
* @see GHIssue#getLabels()
|
* @see GHIssue#getLabels()
|
||||||
* @see GHRepository#listLabels()
|
* @see GHRepository#listLabels()
|
||||||
*/
|
*/
|
||||||
public class GHLabel {
|
public class GHLabel {
|
||||||
private String url, name, color;
|
private String url, name, color, description;
|
||||||
private GHRepository repo;
|
private GHRepository repo;
|
||||||
|
|
||||||
public String getUrl() {
|
public String getUrl() {
|
||||||
@@ -26,6 +31,14 @@ public class GHLabel {
|
|||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Purpose of Label
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
/*package*/ GHLabel wrapUp(GHRepository repo) {
|
/*package*/ GHLabel wrapUp(GHRepository repo) {
|
||||||
this.repo = repo;
|
this.repo = repo;
|
||||||
return this;
|
return this;
|
||||||
@@ -34,4 +47,55 @@ public class GHLabel {
|
|||||||
public void delete() throws IOException {
|
public void delete() throws IOException {
|
||||||
repo.root.retrieve().method("DELETE").to(url);
|
repo.root.retrieve().method("DELETE").to(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param newColor
|
||||||
|
* 6-letter hex color code, like "f29513"
|
||||||
|
*/
|
||||||
|
public void setColor(String newColor) throws IOException {
|
||||||
|
repo.root.retrieve().method("PATCH")
|
||||||
|
.withPreview(SYMMETRA)
|
||||||
|
.with("name", name)
|
||||||
|
.with("color", newColor)
|
||||||
|
.with("description", description)
|
||||||
|
.to(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param newDescription
|
||||||
|
* Description of label
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public void setDescription(String newDescription) throws IOException {
|
||||||
|
repo.root.retrieve().method("PATCH")
|
||||||
|
.withPreview(SYMMETRA)
|
||||||
|
.with("name", name)
|
||||||
|
.with("color", color)
|
||||||
|
.with("description", newDescription)
|
||||||
|
.to(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ static Collection<String> toNames(Collection<GHLabel> labels) {
|
||||||
|
List<String> r = new ArrayList<String>();
|
||||||
|
for (GHLabel l : labels) {
|
||||||
|
r.add(l.getName());
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
final GHLabel ghLabel = (GHLabel) o;
|
||||||
|
return Objects.equals(url, ghLabel.url) &&
|
||||||
|
Objects.equals(name, ghLabel.name) &&
|
||||||
|
Objects.equals(color, ghLabel.color) &&
|
||||||
|
Objects.equals(repo, ghLabel.repo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(url, name, color, repo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
164
src/main/java/org/kohsuke/github/GHLicense.java
Normal file
164
src/main/java/org/kohsuke/github/GHLicense.java
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016, Duncan Dickinson
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GitHub Preview API's license information
|
||||||
|
* <p>
|
||||||
|
*
|
||||||
|
* @author Duncan Dickinson
|
||||||
|
* @see GitHub#getLicense(String)
|
||||||
|
* @see GHRepository#getLicense()
|
||||||
|
* @see <a href="https://developer.github.com/v3/licenses/">https://developer.github.com/v3/licenses/</a>
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"UnusedDeclaration"})
|
||||||
|
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
|
||||||
|
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
|
||||||
|
public class GHLicense extends GHObject {
|
||||||
|
@SuppressFBWarnings("IS2_INCONSISTENT_SYNC") // root is set before the object is returned to the app
|
||||||
|
/*package almost final*/ GitHub root;
|
||||||
|
|
||||||
|
// these fields are always present, even in the short form
|
||||||
|
protected String key, name;
|
||||||
|
|
||||||
|
// the rest is only after populated
|
||||||
|
protected Boolean featured;
|
||||||
|
|
||||||
|
protected String html_url, description, category, implementation, body;
|
||||||
|
|
||||||
|
protected List<String> required = new ArrayList<String>();
|
||||||
|
protected List<String> permitted = new ArrayList<String>();
|
||||||
|
protected List<String> forbidden = new ArrayList<String>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a mnemonic for the license
|
||||||
|
*/
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the license name
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return API URL of this object.
|
||||||
|
*/
|
||||||
|
@WithBridgeMethods(value = String.class, adapterMethod = "urlToString")
|
||||||
|
public URL getUrl() {
|
||||||
|
return GitHub.parseURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Featured licenses are bold in the new repository drop-down
|
||||||
|
*
|
||||||
|
* @return True if the license is featured, false otherwise
|
||||||
|
*/
|
||||||
|
public Boolean isFeatured() throws IOException {
|
||||||
|
populate();
|
||||||
|
return featured;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL getHtmlUrl() throws IOException {
|
||||||
|
populate();
|
||||||
|
return GitHub.parseURL(html_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() throws IOException {
|
||||||
|
populate();
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCategory() throws IOException {
|
||||||
|
populate();
|
||||||
|
return category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getImplementation() throws IOException {
|
||||||
|
populate();
|
||||||
|
return implementation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getRequired() throws IOException {
|
||||||
|
populate();
|
||||||
|
return required;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getPermitted() throws IOException {
|
||||||
|
populate();
|
||||||
|
return permitted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getForbidden() throws IOException {
|
||||||
|
populate();
|
||||||
|
return forbidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBody() throws IOException {
|
||||||
|
populate();
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fully populate the data by retrieving missing data.
|
||||||
|
*
|
||||||
|
* Depending on the original API call where this object is created, it may not contain everything.
|
||||||
|
*/
|
||||||
|
protected synchronized void populate() throws IOException {
|
||||||
|
if (description!=null) return; // already populated
|
||||||
|
|
||||||
|
root.retrieve().to(url, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof GHLicense)) return false;
|
||||||
|
|
||||||
|
GHLicense that = (GHLicense) o;
|
||||||
|
return this.url.equals(that.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return url.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ GHLicense wrap(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
84
src/main/java/org/kohsuke/github/GHMembership.java
Normal file
84
src/main/java/org/kohsuke/github/GHMembership.java
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a membership of a user in an organization.
|
||||||
|
*
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
* @see GHMyself#listOrgMemberships()
|
||||||
|
*/
|
||||||
|
public class GHMembership /* extends GHObject --- but it doesn't have id, created_at, etc. */ {
|
||||||
|
GitHub root;
|
||||||
|
|
||||||
|
String url;
|
||||||
|
String state;
|
||||||
|
String role;
|
||||||
|
GHUser user;
|
||||||
|
GHOrganization organization;
|
||||||
|
|
||||||
|
public URL getUrl() {
|
||||||
|
return GitHub.parseURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public State getState() {
|
||||||
|
return Enum.valueOf(State.class, state.toUpperCase(Locale.ENGLISH));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Role getRole() {
|
||||||
|
return Enum.valueOf(Role.class, role.toUpperCase(Locale.ENGLISH));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHUser getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHOrganization getOrganization() {
|
||||||
|
return organization;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts a pending invitation to an organization.
|
||||||
|
*
|
||||||
|
* @see GHMyself#getMembership(GHOrganization)
|
||||||
|
*/
|
||||||
|
public void activate() throws IOException {
|
||||||
|
root.retrieve().method("PATCH").with("state",State.ACTIVE).to(url,this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ GHMembership wrap(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
if (user!=null) user = root.getUser(user.wrapUp(root));
|
||||||
|
if (organization!=null) organization.wrapUp(root);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ static void wrap(GHMembership[] page, GitHub root) {
|
||||||
|
for (GHMembership m : page)
|
||||||
|
m.wrap(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Role of a user in an organization.
|
||||||
|
*/
|
||||||
|
public enum Role {
|
||||||
|
/**
|
||||||
|
* Organization owner.
|
||||||
|
*/
|
||||||
|
ADMIN,
|
||||||
|
/**
|
||||||
|
* Non-owner organization member.
|
||||||
|
*/
|
||||||
|
MEMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether a role is currently active or waiting for acceptance (pending)
|
||||||
|
*/
|
||||||
|
public enum State {
|
||||||
|
ACTIVE,
|
||||||
|
PENDING;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,8 +27,8 @@ public class GHMilestone extends GHObject {
|
|||||||
return owner;
|
return owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GHUser getCreator() {
|
public GHUser getCreator() throws IOException {
|
||||||
return creator;
|
return root.intern(creator);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Date getDueOn() {
|
public Date getDueOn() {
|
||||||
@@ -72,16 +72,42 @@ public class GHMilestone extends GHObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes this issue.
|
* Closes this milestone.
|
||||||
*/
|
*/
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
edit("state", "closed");
|
edit("state", "closed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reopens this milestone.
|
||||||
|
*/
|
||||||
|
public void reopen() throws IOException {
|
||||||
|
edit("state", "open");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes this milestone.
|
||||||
|
*/
|
||||||
|
public void delete() throws IOException {
|
||||||
|
root.retrieve().method("DELETE").to(getApiRoute());
|
||||||
|
}
|
||||||
|
|
||||||
private void edit(String key, Object value) throws IOException {
|
private void edit(String key, Object value) throws IOException {
|
||||||
new Requester(root)._with(key, value).method("PATCH").to(getApiRoute());
|
new Requester(root)._with(key, value).method("PATCH").to(getApiRoute());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) throws IOException {
|
||||||
|
edit("title", title);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) throws IOException {
|
||||||
|
edit("description", description);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDueOn(Date dueOn) throws IOException {
|
||||||
|
edit("due_on", GitHub.printDate(dueOn));
|
||||||
|
}
|
||||||
|
|
||||||
protected String getApiRoute() {
|
protected String getApiRoute() {
|
||||||
return "/repos/"+owner.getOwnerName()+"/"+owner.getName()+"/milestones/"+number;
|
return "/repos/"+owner.getOwnerName()+"/"+owner.getName()+"/milestones/"+number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
@@ -157,17 +156,13 @@ public class GHMyself extends GHUser {
|
|||||||
* @param repoType type of repository returned in the listing
|
* @param repoType type of repository returned in the listing
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHRepository> listRepositories(final int pageSize, final RepositoryListFilter repoType) {
|
public PagedIterable<GHRepository> listRepositories(final int pageSize, final RepositoryListFilter repoType) {
|
||||||
return new PagedIterable<GHRepository>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHRepository> _iterator(int pageSize) {
|
.with("type",repoType)
|
||||||
return new PagedIterator<GHRepository>(root.retrieve().with("type",repoType).asIterator("/user/repos", GHRepository[].class, pageSize)) {
|
.asPagedIterable(
|
||||||
@Override
|
"/user/repos",
|
||||||
protected void wrapUp(GHRepository[] page) {
|
GHRepository[].class,
|
||||||
for (GHRepository c : page)
|
item -> item.wrap(root)
|
||||||
c.wrap(root);
|
).withPageSize(pageSize);
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}.withPageSize(pageSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -178,6 +173,35 @@ public class GHMyself extends GHUser {
|
|||||||
return listRepositories();
|
return listRepositories();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List your organization memberships
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHMembership> listOrgMemberships() {
|
||||||
|
return listOrgMemberships(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List your organization memberships
|
||||||
|
*
|
||||||
|
* @param state
|
||||||
|
* Filter by a specific state
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHMembership> listOrgMemberships(final GHMembership.State state) {
|
||||||
|
return root.retrieve()
|
||||||
|
.with("state",state)
|
||||||
|
.asPagedIterable(
|
||||||
|
"/user/memberships/orgs",
|
||||||
|
GHMembership[].class,
|
||||||
|
item -> item.wrap(root) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets your membership in a specific organization.
|
||||||
|
*/
|
||||||
|
public GHMembership getMembership(GHOrganization o) throws IOException {
|
||||||
|
return root.retrieve().to("/user/memberships/orgs/"+o.getLogin(),GHMembership.class).wrap(root);
|
||||||
|
}
|
||||||
|
|
||||||
// public void addEmails(Collection<String> emails) throws IOException {
|
// public void addEmails(Collection<String> emails) throws IOException {
|
||||||
//// new Requester(root,ApiVersion.V3).withCredential().to("/user/emails");
|
//// new Requester(root,ApiVersion.V3).withCredential().to("/user/emails");
|
||||||
// root.retrieveWithAuth3()
|
// root.retrieveWithAuth3()
|
||||||
|
|||||||
@@ -2,10 +2,16 @@ package org.kohsuke.github;
|
|||||||
|
|
||||||
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
import javax.annotation.CheckForNull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Most (all?) domain objects in GitHub seems to have these 4 properties.
|
* Most (all?) domain objects in GitHub seems to have these 4 properties.
|
||||||
@@ -13,14 +19,34 @@ import java.util.Date;
|
|||||||
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
|
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
|
||||||
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
|
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
|
||||||
public abstract class GHObject {
|
public abstract class GHObject {
|
||||||
|
/**
|
||||||
|
* Capture response HTTP headers on the state object.
|
||||||
|
*/
|
||||||
|
protected Map<String, List<String>> responseHeaderFields;
|
||||||
|
|
||||||
protected String url;
|
protected String url;
|
||||||
protected int id;
|
protected long id;
|
||||||
protected String created_at;
|
protected String created_at;
|
||||||
protected String updated_at;
|
protected String updated_at;
|
||||||
|
|
||||||
/*package*/ GHObject() {
|
/*package*/ GHObject() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the HTTP response headers given along with the state of this object.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Some of the HTTP headers have nothing to do with the object, for example "Cache-Control"
|
||||||
|
* and others are different depending on how this object was retrieved.
|
||||||
|
*
|
||||||
|
* This method was added as a kind of hack to allow the caller to retrieve OAuth scopes and such.
|
||||||
|
* Use with caution. The method might be removed in the future.
|
||||||
|
*/
|
||||||
|
@CheckForNull @Deprecated
|
||||||
|
public Map<String, List<String>> getResponseHeaderFields() {
|
||||||
|
return responseHeaderFields;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When was this resource created?
|
* When was this resource created?
|
||||||
*/
|
*/
|
||||||
@@ -46,7 +72,7 @@ public abstract class GHObject {
|
|||||||
* URL of this object for humans, which renders some HTML.
|
* URL of this object for humans, which renders some HTML.
|
||||||
*/
|
*/
|
||||||
@WithBridgeMethods(value=String.class, adapterMethod="urlToString")
|
@WithBridgeMethods(value=String.class, adapterMethod="urlToString")
|
||||||
public abstract URL getHtmlUrl();
|
public abstract URL getHtmlUrl() throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When was this resource last updated?
|
* When was this resource last updated?
|
||||||
@@ -58,18 +84,57 @@ public abstract class GHObject {
|
|||||||
/**
|
/**
|
||||||
* Unique ID number of this resource.
|
* Unique ID number of this resource.
|
||||||
*/
|
*/
|
||||||
@WithBridgeMethods(value=String.class, adapterMethod="intToString")
|
@WithBridgeMethods(value={String.class,int.class}, adapterMethod="longToStringOrInt")
|
||||||
public int getId() {
|
public long getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getId")
|
@SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getId")
|
||||||
private Object intToString(int id, Class type) {
|
private Object longToStringOrInt(long id, Class type) {
|
||||||
return String.valueOf(id);
|
if (type==String.class)
|
||||||
|
return String.valueOf(id);
|
||||||
|
if (type==int.class)
|
||||||
|
return (int)id;
|
||||||
|
throw new AssertionError("Unexpected type: "+type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getHtmlUrl")
|
@SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD", justification = "Bridge method of getHtmlUrl")
|
||||||
private Object urlToString(URL url, Class type) {
|
private Object urlToString(URL url, Class type) {
|
||||||
return url==null ? null : url.toString();
|
return url==null ? null : url.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String representation to assist debugging and inspection. The output format of this string
|
||||||
|
* is not a committed part of the API and is subject to change.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new ReflectionToStringBuilder(this, TOSTRING_STYLE, null, null, false, false) {
|
||||||
|
@Override
|
||||||
|
protected boolean accept(Field field) {
|
||||||
|
return super.accept(field) && !field.isAnnotationPresent(SkipFromToString.class);
|
||||||
|
}
|
||||||
|
}.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final ToStringStyle TOSTRING_STYLE = new ToStringStyle() {
|
||||||
|
{
|
||||||
|
this.setUseShortClassName(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void append(StringBuffer buffer, String fieldName, Object value, Boolean fullDetail) {
|
||||||
|
// skip unimportant properties. '_' is a heuristics as important properties tend to have short names
|
||||||
|
if (fieldName.contains("_"))
|
||||||
|
return;
|
||||||
|
// avoid recursing other GHObject
|
||||||
|
if (value instanceof GHObject)
|
||||||
|
return;
|
||||||
|
// likewise no point in showing root
|
||||||
|
if (value instanceof GitHub)
|
||||||
|
return;
|
||||||
|
|
||||||
|
super.append(buffer,fieldName,value,fullDetail);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.util.Collections;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import static org.kohsuke.github.Previews.INERTIA;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Kohsuke Kawaguchi
|
* @author Kohsuke Kawaguchi
|
||||||
@@ -50,7 +51,7 @@ public class GHOrganization extends GHPerson {
|
|||||||
* You use the returned builder to set various properties, then call {@link GHCreateRepositoryBuilder#create()}
|
* You use the returned builder to set various properties, then call {@link GHCreateRepositoryBuilder#create()}
|
||||||
* to finally createa repository.
|
* to finally createa repository.
|
||||||
*/
|
*/
|
||||||
public GHCreateRepositoryBuilder createRepository(String name) throws IOException {
|
public GHCreateRepositoryBuilder createRepository(String name) {
|
||||||
return new GHCreateRepositoryBuilder(root,"/orgs/"+login+"/repos",name);
|
return new GHCreateRepositoryBuilder(root,"/orgs/"+login+"/repos",name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,17 +70,11 @@ public class GHOrganization extends GHPerson {
|
|||||||
* List up all the teams.
|
* List up all the teams.
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHTeam> listTeams() throws IOException {
|
public PagedIterable<GHTeam> listTeams() throws IOException {
|
||||||
return new PagedIterable<GHTeam>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHTeam> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHTeam>(root.retrieve().asIterator(String.format("/orgs/%s/teams", login), GHTeam[].class, pageSize)) {
|
String.format("/orgs/%s/teams", login),
|
||||||
@Override
|
GHTeam[].class,
|
||||||
protected void wrapUp(GHTeam[] page) {
|
item -> item.wrapUp(GHOrganization.this) );
|
||||||
for (GHTeam c : page)
|
|
||||||
c.wrapUp(GHOrganization.this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,6 +88,33 @@ public class GHOrganization extends GHPerson {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a team that has the given slug in its {@link GHTeam#getSlug()}
|
||||||
|
*/
|
||||||
|
public GHTeam getTeamBySlug(String slug) throws IOException {
|
||||||
|
for (GHTeam t : listTeams()) {
|
||||||
|
if(t.getSlug().equals(slug))
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Member's role in an organization */
|
||||||
|
public enum Role {
|
||||||
|
ADMIN, /** The user is an owner of the organization. */
|
||||||
|
MEMBER /** The user is a non-owner member of the organization. */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds (invites) a user to the organization.
|
||||||
|
* @see <a href="https://developer.github.com/v3/orgs/members/#add-or-update-organization-membership">documentation</a>
|
||||||
|
*/
|
||||||
|
public void add(GHUser user, Role role) throws IOException {
|
||||||
|
root.retrieve().method("PUT")
|
||||||
|
.with("role", role.name().toLowerCase())
|
||||||
|
.to("/orgs/" + login + "/memberships/" + user.getLogin());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if this organization has the specified user as a member.
|
* Checks if this organization has the specified user as a member.
|
||||||
*/
|
*/
|
||||||
@@ -162,17 +184,12 @@ public class GHOrganization extends GHPerson {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PagedIterable<GHUser> listMembers(final String suffix, final String filter) throws IOException {
|
private PagedIterable<GHUser> listMembers(final String suffix, final String filter) throws IOException {
|
||||||
return new PagedIterable<GHUser>() {
|
String filterParams = (filter == null) ? "" : ("?filter=" + filter);
|
||||||
public PagedIterator<GHUser> _iterator(int pageSize) {
|
return root.retrieve()
|
||||||
String filterParams = (filter == null) ? "" : ("?filter=" + filter);
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHUser>(root.retrieve().asIterator(String.format("/orgs/%s/%s%s", login, suffix, filterParams), GHUser[].class, pageSize)) {
|
String.format("/orgs/%s/%s%s", login, suffix, filterParams),
|
||||||
@Override
|
GHUser[].class,
|
||||||
protected void wrapUp(GHUser[] users) {
|
item -> item.wrapUp(root) );
|
||||||
GHUser.wrap(users, root);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -182,6 +199,37 @@ public class GHOrganization extends GHPerson {
|
|||||||
root.retrieve().method("DELETE").to("/orgs/" + login + "/public_members/" + u.getLogin(), null);
|
root.retrieve().method("DELETE").to("/orgs/" + login + "/public_members/" + u.getLogin(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the projects for this organization.
|
||||||
|
* @param status The status filter (all, open or closed).
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHProject> listProjects(final GHProject.ProjectStateFilter status) throws IOException {
|
||||||
|
return root.retrieve().withPreview(INERTIA)
|
||||||
|
.with("state", status)
|
||||||
|
.asPagedIterable(
|
||||||
|
String.format("/orgs/%s/projects", login),
|
||||||
|
GHProject[].class,
|
||||||
|
item -> item.wrap(root) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all open projects for the organization.
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHProject> listProjects() throws IOException {
|
||||||
|
return listProjects(GHProject.ProjectStateFilter.OPEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a project for the organization.
|
||||||
|
*/
|
||||||
|
public GHProject createProject(String name, String body) throws IOException {
|
||||||
|
return root.retrieve().method("POST")
|
||||||
|
.withPreview(INERTIA)
|
||||||
|
.with("name", name)
|
||||||
|
.with("body", body)
|
||||||
|
.to(String.format("/orgs/%s/projects", login), GHProject.class).wrap(root);
|
||||||
|
}
|
||||||
|
|
||||||
public enum Permission { ADMIN, PUSH, PULL }
|
public enum Permission { ADMIN, PUSH, PULL }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -191,7 +239,7 @@ public class GHOrganization extends GHPerson {
|
|||||||
Requester post = new Requester(root).with("name", name).with("permission", p);
|
Requester post = new Requester(root).with("name", name).with("permission", p);
|
||||||
List<String> repo_names = new ArrayList<String>();
|
List<String> repo_names = new ArrayList<String>();
|
||||||
for (GHRepository r : repositories) {
|
for (GHRepository r : repositories) {
|
||||||
repo_names.add(r.getName());
|
repo_names.add(login + "/" + r.getName());
|
||||||
}
|
}
|
||||||
post.with("repo_names",repo_names);
|
post.with("repo_names",repo_names);
|
||||||
return post.method("POST").to("/orgs/" + login + "/teams", GHTeam.class).wrapUp(this);
|
return post.method("POST").to("/orgs/" + login + "/teams", GHTeam.class).wrapUp(this);
|
||||||
@@ -209,7 +257,7 @@ public class GHOrganization extends GHPerson {
|
|||||||
*/
|
*/
|
||||||
public List<GHRepository> getRepositoriesWithOpenPullRequests() throws IOException {
|
public List<GHRepository> getRepositoriesWithOpenPullRequests() throws IOException {
|
||||||
List<GHRepository> r = new ArrayList<GHRepository>();
|
List<GHRepository> r = new ArrayList<GHRepository>();
|
||||||
for (GHRepository repository : listRepositories()) {
|
for (GHRepository repository : listRepositories(100)) {
|
||||||
repository.wrap(root);
|
repository.wrap(root);
|
||||||
List<GHPullRequest> pullRequests = repository.getPullRequests(GHIssueState.OPEN);
|
List<GHPullRequest> pullRequests = repository.getPullRequests(GHIssueState.OPEN);
|
||||||
if (pullRequests.size() > 0) {
|
if (pullRequests.size() > 0) {
|
||||||
@@ -234,17 +282,11 @@ public class GHOrganization extends GHPerson {
|
|||||||
* Lists events performed by a user (this includes private events if the caller is authenticated.
|
* Lists events performed by a user (this includes private events if the caller is authenticated.
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHEventInfo> listEvents() throws IOException {
|
public PagedIterable<GHEventInfo> listEvents() throws IOException {
|
||||||
return new PagedIterable<GHEventInfo>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHEventInfo> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHEventInfo>(root.retrieve().asIterator(String.format("/orgs/%s/events", login), GHEventInfo[].class, pageSize)) {
|
String.format("/orgs/%s/events", login),
|
||||||
@Override
|
GHEventInfo[].class,
|
||||||
protected void wrapUp(GHEventInfo[] page) {
|
item -> item.wrapUp(root) );
|
||||||
for (GHEventInfo c : page)
|
|
||||||
c.wrapUp(root);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -256,17 +298,12 @@ public class GHOrganization extends GHPerson {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public PagedIterable<GHRepository> listRepositories(final int pageSize) {
|
public PagedIterable<GHRepository> listRepositories(final int pageSize) {
|
||||||
return new PagedIterable<GHRepository>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHRepository> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHRepository>(root.retrieve().asIterator("/orgs/" + login + "/repos?per_page=" + pageSize, GHRepository[].class, pageSize)) {
|
"/orgs/" + login + "/repos",
|
||||||
@Override
|
GHRepository[].class,
|
||||||
protected void wrapUp(GHRepository[] page) {
|
item -> item.wrap(root)
|
||||||
for (GHRepository c : page)
|
).withPageSize(pageSize);
|
||||||
c.wrap(root);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
59
src/main/java/org/kohsuke/github/GHPermission.java
Normal file
59
src/main/java/org/kohsuke/github/GHPermission.java
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2016 CloudBees, Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permission for a user in a repository.
|
||||||
|
* @see <a href="https://developer.github.com/v3/repos/collaborators/#review-a-users-permission-level">API</a>
|
||||||
|
*/
|
||||||
|
/*package*/ class GHPermission {
|
||||||
|
|
||||||
|
private String permission;
|
||||||
|
private GHUser user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return one of {@code admin}, {@code write}, {@code read}, or {@code none}
|
||||||
|
*/
|
||||||
|
public String getPermission() {
|
||||||
|
return permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHPermissionType getPermissionType() {
|
||||||
|
return Enum.valueOf(GHPermissionType.class, permission.toUpperCase(Locale.ENGLISH));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHUser getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wrapUp(GitHub root) {
|
||||||
|
if (user != null) {
|
||||||
|
user.root = root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
11
src/main/java/org/kohsuke/github/GHPermissionType.java
Normal file
11
src/main/java/org/kohsuke/github/GHPermissionType.java
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
*/
|
||||||
|
public enum GHPermissionType {
|
||||||
|
ADMIN,
|
||||||
|
WRITE,
|
||||||
|
READ,
|
||||||
|
NONE
|
||||||
|
}
|
||||||
@@ -38,8 +38,12 @@ public abstract class GHPerson extends GHObject {
|
|||||||
* Depending on the original API call where this object is created, it may not contain everything.
|
* Depending on the original API call where this object is created, it may not contain everything.
|
||||||
*/
|
*/
|
||||||
protected synchronized void populate() throws IOException {
|
protected synchronized void populate() throws IOException {
|
||||||
if (created_at!=null) return; // already populated
|
if (created_at!=null) {
|
||||||
|
return; // already populated
|
||||||
|
}
|
||||||
|
if (root == null || root.isOffline()) {
|
||||||
|
return; // cannot populate, will have to live with what we have
|
||||||
|
}
|
||||||
root.retrieve().to(url, this);
|
root.retrieve().to(url, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +56,7 @@ public abstract class GHPerson extends GHObject {
|
|||||||
*/
|
*/
|
||||||
public synchronized Map<String,GHRepository> getRepositories() throws IOException {
|
public synchronized Map<String,GHRepository> getRepositories() throws IOException {
|
||||||
Map<String,GHRepository> repositories = new TreeMap<String, GHRepository>();
|
Map<String,GHRepository> repositories = new TreeMap<String, GHRepository>();
|
||||||
for (GHRepository r : listRepositories()) {
|
for (GHRepository r : listRepositories(100)) {
|
||||||
repositories.put(r.getName(),r);
|
repositories.put(r.getName(),r);
|
||||||
}
|
}
|
||||||
return Collections.unmodifiableMap(repositories);
|
return Collections.unmodifiableMap(repositories);
|
||||||
@@ -75,36 +79,32 @@ public abstract class GHPerson extends GHObject {
|
|||||||
* Unlike {@link #getRepositories()}, this does not wait until all the repositories are returned.
|
* Unlike {@link #getRepositories()}, this does not wait until all the repositories are returned.
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHRepository> listRepositories(final int pageSize) {
|
public PagedIterable<GHRepository> listRepositories(final int pageSize) {
|
||||||
return new PagedIterable<GHRepository>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHRepository> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHRepository>(root.retrieve().asIterator("/users/" + login + "/repos?per_page=" + pageSize, GHRepository[].class, pageSize)) {
|
"/users/" + login + "/repos",
|
||||||
@Override
|
GHRepository[].class,
|
||||||
protected void wrapUp(GHRepository[] page) {
|
item -> item.wrap(root)
|
||||||
for (GHRepository c : page)
|
).withPageSize(pageSize);
|
||||||
c.wrap(root);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads repository list in a pagenated fashion.
|
* Loads repository list in a paginated fashion.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* For a person with a lot of repositories, GitHub returns the list of repositories in a pagenated fashion.
|
* For a person with a lot of repositories, GitHub returns the list of repositories in a paginated fashion.
|
||||||
* Unlike {@link #getRepositories()}, this method allows the caller to start processing data as it arrives.
|
* Unlike {@link #getRepositories()}, this method allows the caller to start processing data as it arrives.
|
||||||
*
|
*
|
||||||
* Every {@link Iterator#next()} call results in I/O. Exceptions that occur during the processing is wrapped
|
* Every {@link Iterator#next()} call results in I/O. Exceptions that occur during the processing is wrapped
|
||||||
* into {@link Error}.
|
* into {@link Error}.
|
||||||
*
|
*
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* Use {@link #listRepositories()}
|
* Use {@link #listRepositories()}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public synchronized Iterable<List<GHRepository>> iterateRepositories(final int pageSize) {
|
public synchronized Iterable<List<GHRepository>> iterateRepositories(final int pageSize) {
|
||||||
return new Iterable<List<GHRepository>>() {
|
return new Iterable<List<GHRepository>>() {
|
||||||
public Iterator<List<GHRepository>> iterator() {
|
public Iterator<List<GHRepository>> iterator() {
|
||||||
final Iterator<GHRepository[]> pager = root.retrieve().asIterator("/users/" + login + "/repos?per_page="+pageSize,GHRepository[].class, pageSize);
|
final Iterator<GHRepository[]> pager = root.retrieve().asIterator("/users/" + login + "/repos",GHRepository[].class, pageSize);
|
||||||
|
|
||||||
return new Iterator<List<GHRepository>>() {
|
return new Iterator<List<GHRepository>>() {
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
@@ -204,7 +204,7 @@ public abstract class GHPerson extends GHObject {
|
|||||||
|
|
||||||
public Date getUpdatedAt() throws IOException {
|
public Date getUpdatedAt() throws IOException {
|
||||||
populate();
|
populate();
|
||||||
return super.getCreatedAt();
|
return super.getUpdatedAt();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
183
src/main/java/org/kohsuke/github/GHProject.java
Normal file
183
src/main/java/org/kohsuke/github/GHProject.java
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright 2018 Martin van Zijl.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.INERTIA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GitHub project.
|
||||||
|
* @see <a href="https://developer.github.com/v3/projects/">Projects</a>
|
||||||
|
* @author Martin van Zijl
|
||||||
|
*/
|
||||||
|
public class GHProject extends GHObject {
|
||||||
|
protected GitHub root;
|
||||||
|
protected GHObject owner;
|
||||||
|
|
||||||
|
private String owner_url;
|
||||||
|
private String html_url;
|
||||||
|
private String node_id;
|
||||||
|
private String name;
|
||||||
|
private String body;
|
||||||
|
private int number;
|
||||||
|
private String state;
|
||||||
|
private GHUser creator;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL getHtmlUrl() throws IOException {
|
||||||
|
return GitHub.parseURL(html_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitHub getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHObject getOwner() throws IOException {
|
||||||
|
if(owner == null) {
|
||||||
|
try {
|
||||||
|
if(owner_url.contains("/orgs/")) {
|
||||||
|
owner = root.retrieve().to(getOwnerUrl().getPath(), GHOrganization.class).wrapUp(root);
|
||||||
|
} else if(owner_url.contains("/users/")) {
|
||||||
|
owner = root.retrieve().to(getOwnerUrl().getPath(), GHUser.class).wrapUp(root);
|
||||||
|
} else if(owner_url.contains("/repos/")) {
|
||||||
|
owner = root.retrieve().to(getOwnerUrl().getPath(), GHRepository.class).wrap(root);
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL getOwnerUrl() {
|
||||||
|
return GitHub.parseURL(owner_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNode_id() {
|
||||||
|
return node_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumber() {
|
||||||
|
return number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProjectState getState() {
|
||||||
|
return Enum.valueOf(ProjectState.class, state.toUpperCase(Locale.ENGLISH));
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHUser getCreator() {
|
||||||
|
return creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProject wrap(GHRepository repo) {
|
||||||
|
this.owner = repo;
|
||||||
|
this.root = repo.root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProject wrap(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void edit(String key, Object value) throws IOException {
|
||||||
|
new Requester(root).withPreview(INERTIA)._with(key, value).method("PATCH").to(getApiRoute());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getApiRoute() {
|
||||||
|
return "/projects/" + id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) throws IOException {
|
||||||
|
edit("name", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBody(String body) throws IOException {
|
||||||
|
edit("body", body);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ProjectState {
|
||||||
|
OPEN,
|
||||||
|
CLOSED
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(ProjectState state) throws IOException {
|
||||||
|
edit("state", state.toString().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static enum ProjectStateFilter {
|
||||||
|
ALL,
|
||||||
|
OPEN,
|
||||||
|
CLOSED
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the permission level that all members of the project's organization will have on this project.
|
||||||
|
* Only applicable for organization-owned projects.
|
||||||
|
*/
|
||||||
|
public void setOrganizationPermission(GHPermissionType permission) throws IOException {
|
||||||
|
edit("organization_permission", permission.toString().toLowerCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets visibility of the project within the organization.
|
||||||
|
* Only applicable for organization-owned projects.
|
||||||
|
*/
|
||||||
|
public void setPublic(boolean isPublic) throws IOException {
|
||||||
|
edit("public", isPublic);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete() throws IOException {
|
||||||
|
new Requester(root).withPreview(INERTIA).method("DELETE").to(getApiRoute());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PagedIterable<GHProjectColumn> listColumns() throws IOException {
|
||||||
|
final GHProject project = this;
|
||||||
|
return root.retrieve()
|
||||||
|
.withPreview(INERTIA)
|
||||||
|
.asPagedIterable(
|
||||||
|
String.format("/projects/%d/columns", id),
|
||||||
|
GHProjectColumn[].class,
|
||||||
|
item -> item.wrap(project) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProjectColumn createColumn(String name) throws IOException {
|
||||||
|
return root.retrieve().method("POST")
|
||||||
|
.withPreview(INERTIA)
|
||||||
|
.with("name", name)
|
||||||
|
.to(String.format("/projects/%d/columns", id), GHProjectColumn.class).wrap(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
123
src/main/java/org/kohsuke/github/GHProjectCard.java
Normal file
123
src/main/java/org/kohsuke/github/GHProjectCard.java
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.INERTIA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gunnar Skjold
|
||||||
|
*/
|
||||||
|
public class GHProjectCard extends GHObject {
|
||||||
|
private GitHub root;
|
||||||
|
private GHProject project;
|
||||||
|
private GHProjectColumn column;
|
||||||
|
|
||||||
|
private String note;
|
||||||
|
private GHUser creator;
|
||||||
|
private String content_url, project_url, column_url;
|
||||||
|
private boolean archived;
|
||||||
|
|
||||||
|
public URL getHtmlUrl() throws IOException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProjectCard wrap(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProjectCard wrap(GHProjectColumn column) {
|
||||||
|
this.column = column;
|
||||||
|
this.project = column.project;
|
||||||
|
this.root = column.root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitHub getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProject getProject() throws IOException {
|
||||||
|
if(project == null) {
|
||||||
|
try {
|
||||||
|
project = root.retrieve().to(getProjectUrl().getPath(), GHProject.class).wrap(root);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProjectColumn getColumn() throws IOException {
|
||||||
|
if(column == null) {
|
||||||
|
try {
|
||||||
|
column = root.retrieve().to(getColumnUrl().getPath(), GHProjectColumn.class).wrap(root);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return column;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHIssue getContent() throws IOException {
|
||||||
|
if(StringUtils.isEmpty(content_url))
|
||||||
|
return null;
|
||||||
|
try {
|
||||||
|
if(content_url.contains("/pulls")) {
|
||||||
|
return root.retrieve().to(getContentUrl().getPath(), GHPullRequest.class).wrap(root);
|
||||||
|
} else {
|
||||||
|
return root.retrieve().to(getContentUrl().getPath(), GHIssue.class).wrap(root);
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNote() {
|
||||||
|
return note;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHUser getCreator() {
|
||||||
|
return creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL getContentUrl() {
|
||||||
|
return GitHub.parseURL(content_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL getProjectUrl() {
|
||||||
|
return GitHub.parseURL(project_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL getColumnUrl() {
|
||||||
|
return GitHub.parseURL(column_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isArchived() {
|
||||||
|
return archived;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNote(String note) throws IOException {
|
||||||
|
edit("note", note);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArchived(boolean archived) throws IOException {
|
||||||
|
edit("archived", archived);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void edit(String key, Object value) throws IOException {
|
||||||
|
new Requester(root).withPreview(INERTIA)._with(key, value).method("PATCH").to(getApiRoute());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getApiRoute() {
|
||||||
|
return String.format("/projects/columns/cards/%d", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete() throws IOException {
|
||||||
|
new Requester(root).withPreview(INERTIA).method("DELETE").to(getApiRoute());
|
||||||
|
}
|
||||||
|
}
|
||||||
98
src/main/java/org/kohsuke/github/GHProjectColumn.java
Normal file
98
src/main/java/org/kohsuke/github/GHProjectColumn.java
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.INERTIA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Gunnar Skjold
|
||||||
|
*/
|
||||||
|
public class GHProjectColumn extends GHObject {
|
||||||
|
protected GitHub root;
|
||||||
|
protected GHProject project;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String project_url;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL getHtmlUrl() throws IOException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProjectColumn wrap(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProjectColumn wrap(GHProject project) {
|
||||||
|
this.project = project;
|
||||||
|
this.root = project.root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitHub getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProject getProject() throws IOException {
|
||||||
|
if(project == null) {
|
||||||
|
try {
|
||||||
|
project = root.retrieve().to(getProjectUrl().getPath(), GHProject.class).wrap(root);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public URL getProjectUrl() {
|
||||||
|
return GitHub.parseURL(project_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) throws IOException {
|
||||||
|
edit("name", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void edit(String key, Object value) throws IOException {
|
||||||
|
new Requester(root).withPreview(INERTIA)._with(key, value).method("PATCH").to(getApiRoute());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getApiRoute() {
|
||||||
|
return String.format("/projects/columns/%d", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete() throws IOException {
|
||||||
|
new Requester(root).withPreview(INERTIA).method("DELETE").to(getApiRoute());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PagedIterable<GHProjectCard> listCards() throws IOException {
|
||||||
|
final GHProjectColumn column = this;
|
||||||
|
return root.retrieve()
|
||||||
|
.withPreview(INERTIA)
|
||||||
|
.asPagedIterable(
|
||||||
|
String.format("/projects/columns/%d/cards", id),
|
||||||
|
GHProjectCard[].class,
|
||||||
|
item -> item.wrap(column) );
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProjectCard createCard(String note) throws IOException {
|
||||||
|
return root.retrieve().method("POST")
|
||||||
|
.withPreview(INERTIA)
|
||||||
|
.with("note", note)
|
||||||
|
.to(String.format("/projects/columns/%d/cards", id), GHProjectCard.class).wrap(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProjectCard createCard(GHIssue issue) throws IOException {
|
||||||
|
return root.retrieve().method("POST")
|
||||||
|
.withPreview(INERTIA)
|
||||||
|
.with("content_type", issue instanceof GHPullRequest ? "PullRequest" : "Issue")
|
||||||
|
.with("content_id", issue.getId())
|
||||||
|
.to(String.format("/projects/columns/%d/cards", id), GHProjectCard.class).wrap(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,19 +23,29 @@
|
|||||||
*/
|
*/
|
||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import javax.annotation.CheckForNull;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.SHADOW_CAT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A pull request.
|
* A pull request.
|
||||||
*
|
*
|
||||||
* @author Kohsuke Kawaguchi
|
* @author Kohsuke Kawaguchi
|
||||||
* @see GHRepository#getPullRequest(int)
|
* @see GHRepository#getPullRequest(int)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"UnusedDeclaration"})
|
@SuppressWarnings({"UnusedDeclaration"})
|
||||||
public class GHPullRequest extends GHIssue {
|
public class GHPullRequest extends GHIssue implements Refreshable {
|
||||||
|
|
||||||
|
private static final String COMMENTS_ACTION = "/comments";
|
||||||
|
private static final String REQUEST_REVIEWERS = "/requested_reviewers";
|
||||||
|
|
||||||
private String patch_url, diff_url, issue_url;
|
private String patch_url, diff_url, issue_url;
|
||||||
private GHCommitPointer base;
|
private GHCommitPointer base;
|
||||||
@@ -44,14 +54,20 @@ public class GHPullRequest extends GHIssue {
|
|||||||
|
|
||||||
// details that are only available when obtained from ID
|
// details that are only available when obtained from ID
|
||||||
private GHUser merged_by;
|
private GHUser merged_by;
|
||||||
private int review_comments, additions;
|
private int review_comments, additions, commits;
|
||||||
private boolean merged;
|
private boolean merged, maintainer_can_modify;
|
||||||
|
// making these package private to all for testing
|
||||||
|
boolean draft;
|
||||||
private Boolean mergeable;
|
private Boolean mergeable;
|
||||||
private int deletions;
|
private int deletions;
|
||||||
private String mergeable_state;
|
private String mergeable_state;
|
||||||
private int changed_files;
|
private int changed_files;
|
||||||
private String merge_commit_sha;
|
private String merge_commit_sha;
|
||||||
|
|
||||||
|
// pull request reviewers
|
||||||
|
private GHUser[] requested_reviewers;
|
||||||
|
private GHTeam[] requested_teams;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GitHub doesn't return some properties of {@link GHIssue} when requesting the GET on the 'pulls' API
|
* GitHub doesn't return some properties of {@link GHIssue} when requesting the GET on the 'pulls' API
|
||||||
* route as opposed to 'issues' API route. This flag remembers whether we made the GET call on the 'issues' route
|
* route as opposed to 'issues' API route. This flag remembers whether we made the GET call on the 'issues' route
|
||||||
@@ -70,6 +86,8 @@ public class GHPullRequest extends GHIssue {
|
|||||||
if (base != null) base.wrapUp(root);
|
if (base != null) base.wrapUp(root);
|
||||||
if (head != null) head.wrapUp(root);
|
if (head != null) head.wrapUp(root);
|
||||||
if (merged_by != null) merged_by.wrapUp(root);
|
if (merged_by != null) merged_by.wrapUp(root);
|
||||||
|
if (requested_reviewers != null) GHUser.wrap(requested_reviewers, root);
|
||||||
|
if (requested_teams != null) GHTeam.wrapUp(requested_teams, this);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +103,7 @@ public class GHPullRequest extends GHIssue {
|
|||||||
public URL getPatchUrl() {
|
public URL getPatchUrl() {
|
||||||
return GitHub.parseURL(patch_url);
|
return GitHub.parseURL(patch_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The URL of the patch file.
|
* The URL of the patch file.
|
||||||
* like https://github.com/jenkinsci/jenkins/pull/100.patch
|
* like https://github.com/jenkinsci/jenkins/pull/100.patch
|
||||||
@@ -108,7 +126,7 @@ public class GHPullRequest extends GHIssue {
|
|||||||
public GHCommitPointer getHead() {
|
public GHCommitPointer getHead() {
|
||||||
return head;
|
return head;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public Date getIssueUpdatedAt() throws IOException {
|
public Date getIssueUpdatedAt() throws IOException {
|
||||||
return super.getUpdatedAt();
|
return super.getUpdatedAt();
|
||||||
@@ -161,16 +179,48 @@ public class GHPullRequest extends GHIssue {
|
|||||||
return additions;
|
return additions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getCommits() throws IOException {
|
||||||
|
populate();
|
||||||
|
return commits;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isMerged() throws IOException {
|
public boolean isMerged() throws IOException {
|
||||||
populate();
|
populate();
|
||||||
return merged;
|
return merged;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getMergeable() throws IOException {
|
public boolean canMaintainerModify() throws IOException {
|
||||||
populate();
|
populate();
|
||||||
|
return maintainer_can_modify;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDraft() throws IOException {
|
||||||
|
populate();
|
||||||
|
return draft;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this PR mergeable?
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* null if the state has not been determined yet, for example when a PR is newly created.
|
||||||
|
* If this method is called on an instance whose mergeable state is not yet known,
|
||||||
|
* API call is made to retrieve the latest state.
|
||||||
|
*/
|
||||||
|
public Boolean getMergeable() throws IOException {
|
||||||
|
refresh(mergeable);
|
||||||
return mergeable;
|
return mergeable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* for test purposes only
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
Boolean getMergeableNoRefresh() throws IOException {
|
||||||
|
return mergeable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public int getDeletions() throws IOException {
|
public int getDeletions() throws IOException {
|
||||||
populate();
|
populate();
|
||||||
return deletions;
|
return deletions;
|
||||||
@@ -194,67 +244,106 @@ public class GHPullRequest extends GHIssue {
|
|||||||
return merge_commit_sha;
|
return merge_commit_sha;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<GHUser> getRequestedReviewers() throws IOException {
|
||||||
|
refresh(requested_reviewers);
|
||||||
|
return Collections.unmodifiableList(Arrays.asList(requested_reviewers));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<GHTeam> getRequestedTeams() throws IOException {
|
||||||
|
refresh(requested_teams);
|
||||||
|
return Collections.unmodifiableList(Arrays.asList(requested_teams));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fully populate the data by retrieving missing data.
|
* Fully populate the data by retrieving missing data.
|
||||||
*
|
*
|
||||||
* Depending on the original API call where this object is created, it may not contain everything.
|
* Depending on the original API call where this object is created, it may not contain everything.
|
||||||
*/
|
*/
|
||||||
private void populate() throws IOException {
|
private void populate() throws IOException {
|
||||||
if (merged_by!=null) return; // already populated
|
if (mergeable_state!=null) return; // already populated
|
||||||
|
refresh();
|
||||||
root.retrieve().to(url, this).wrapUp(owner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves all the commits associated to this pull request.
|
* Repopulates this object.
|
||||||
|
*/
|
||||||
|
public void refresh() throws IOException {
|
||||||
|
if (root.isOffline()) {
|
||||||
|
return; // cannot populate, will have to live with what we have
|
||||||
|
}
|
||||||
|
root.retrieve()
|
||||||
|
.withPreview(SHADOW_CAT)
|
||||||
|
.to(url, this).wrapUp(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves all the files associated to this pull request.
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHPullRequestFileDetail> listFiles() {
|
public PagedIterable<GHPullRequestFileDetail> listFiles() {
|
||||||
return new PagedIterable<GHPullRequestFileDetail>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHPullRequestFileDetail> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHPullRequestFileDetail>(root.retrieve().asIterator(String.format("%s/files", getApiURL()),
|
String.format("%s/files", getApiRoute()),
|
||||||
GHPullRequestFileDetail[].class, pageSize)) {
|
GHPullRequestFileDetail[].class,
|
||||||
@Override
|
null);
|
||||||
protected void wrapUp(GHPullRequestFileDetail[] page) {
|
}
|
||||||
}
|
|
||||||
};
|
/**
|
||||||
}
|
* Retrieves all the reviews associated to this pull request.
|
||||||
};
|
*/
|
||||||
|
public PagedIterable<GHPullRequestReview> listReviews() {
|
||||||
|
return root.retrieve()
|
||||||
|
.asPagedIterable(
|
||||||
|
String.format("%s/reviews", getApiRoute()),
|
||||||
|
GHPullRequestReview[].class,
|
||||||
|
item -> item.wrapUp(GHPullRequest.this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Obtains all the review comments associated with this pull request.
|
* Obtains all the review comments associated with this pull request.
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHPullRequestReviewComment> listReviewComments() throws IOException {
|
public PagedIterable<GHPullRequestReviewComment> listReviewComments() throws IOException {
|
||||||
return new PagedIterable<GHPullRequestReviewComment>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHPullRequestReviewComment> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHPullRequestReviewComment>(root.retrieve().asIterator(getApiRoute() + "/comments",
|
getApiRoute() + COMMENTS_ACTION,
|
||||||
GHPullRequestReviewComment[].class, pageSize)) {
|
GHPullRequestReviewComment[].class,
|
||||||
protected void wrapUp(GHPullRequestReviewComment[] page) {
|
item -> item.wrapUp(GHPullRequest.this) );
|
||||||
for (GHPullRequestReviewComment c : page)
|
|
||||||
c.wrapUp(GHPullRequest.this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves all the commits associated to this pull request.
|
* Retrieves all the commits associated to this pull request.
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHPullRequestCommitDetail> listCommits() {
|
public PagedIterable<GHPullRequestCommitDetail> listCommits() {
|
||||||
return new PagedIterable<GHPullRequestCommitDetail>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHPullRequestCommitDetail> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHPullRequestCommitDetail>(root.retrieve().asIterator(
|
String.format("%s/commits", getApiRoute()),
|
||||||
String.format("%s/commits", getApiURL()),
|
GHPullRequestCommitDetail[].class,
|
||||||
GHPullRequestCommitDetail[].class, pageSize)) {
|
item -> item.wrapUp(GHPullRequest.this) );
|
||||||
@Override
|
}
|
||||||
protected void wrapUp(GHPullRequestCommitDetail[] page) {
|
|
||||||
for (GHPullRequestCommitDetail c : page)
|
/**
|
||||||
c.wrapUp(GHPullRequest.this);
|
* @deprecated
|
||||||
}
|
* Use {@link #createReview()}
|
||||||
};
|
*/
|
||||||
}
|
public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event,
|
||||||
};
|
GHPullRequestReviewComment... comments) throws IOException {
|
||||||
|
return createReview(body, event, Arrays.asList(comments));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Use {@link #createReview()}
|
||||||
|
*/
|
||||||
|
public GHPullRequestReview createReview(String body, @CheckForNull GHPullRequestReviewState event,
|
||||||
|
List<GHPullRequestReviewComment> comments) throws IOException {
|
||||||
|
GHPullRequestReviewBuilder b = createReview().body(body);
|
||||||
|
for (GHPullRequestReviewComment c : comments) {
|
||||||
|
b.comment(c.getBody(), c.getPath(), c.getPosition());
|
||||||
|
}
|
||||||
|
return b.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHPullRequestReviewBuilder createReview() {
|
||||||
|
return new GHPullRequestReviewBuilder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GHPullRequestReviewComment createReviewComment(String body, String sha, String path, int position) throws IOException {
|
public GHPullRequestReviewComment createReviewComment(String body, String sha, String path, int position) throws IOException {
|
||||||
@@ -263,7 +352,23 @@ public class GHPullRequest extends GHIssue {
|
|||||||
.with("commit_id", sha)
|
.with("commit_id", sha)
|
||||||
.with("path", path)
|
.with("path", path)
|
||||||
.with("position", position)
|
.with("position", position)
|
||||||
.to(getApiRoute() + "/comments", GHPullRequestReviewComment.class).wrapUp(this);
|
.to(getApiRoute() + COMMENTS_ACTION, GHPullRequestReviewComment.class).wrapUp(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestReviewers(List<GHUser> reviewers) throws IOException {
|
||||||
|
new Requester(root).method("POST")
|
||||||
|
.withLogins("reviewers", reviewers)
|
||||||
|
.to(getApiRoute() + REQUEST_REVIEWERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void requestTeamReviewers(List<GHTeam> teams) throws IOException {
|
||||||
|
List<String> teamReviewers = new ArrayList<String>(teams.size());
|
||||||
|
for (GHTeam team : teams) {
|
||||||
|
teamReviewers.add(team.getSlug());
|
||||||
|
}
|
||||||
|
new Requester(root).method("POST")
|
||||||
|
.with("team_reviewers", teamReviewers)
|
||||||
|
.to(getApiRoute() + REQUEST_REVIEWERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,12 +394,32 @@ public class GHPullRequest extends GHIssue {
|
|||||||
* SHA that pull request head must match to allow merge.
|
* SHA that pull request head must match to allow merge.
|
||||||
*/
|
*/
|
||||||
public void merge(String msg, String sha) throws IOException {
|
public void merge(String msg, String sha) throws IOException {
|
||||||
new Requester(root).method("PUT").with("commit_message",msg).with("sha",sha).to(getApiRoute()+"/merge");
|
merge(msg, sha, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merge this pull request, using the specified merge method.
|
||||||
|
*
|
||||||
|
* The equivalent of the big green "Merge pull request" button.
|
||||||
|
*
|
||||||
|
* @param msg
|
||||||
|
* Commit message. If null, the default one will be used.
|
||||||
|
* @param method
|
||||||
|
* SHA that pull request head must match to allow merge.
|
||||||
|
*/
|
||||||
|
public void merge(String msg, String sha, MergeMethod method) throws IOException {
|
||||||
|
new Requester(root).method("PUT")
|
||||||
|
.with("commit_message", msg)
|
||||||
|
.with("sha", sha)
|
||||||
|
.with("merge_method", method)
|
||||||
|
.to(getApiRoute() + "/merge");
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum MergeMethod{ MERGE, SQUASH, REBASE }
|
||||||
|
|
||||||
private void fetchIssue() throws IOException {
|
private void fetchIssue() throws IOException {
|
||||||
if (!fetchedIssueDetails) {
|
if (!fetchedIssueDetails) {
|
||||||
new Requester(root).to(getIssuesApiRoute(), this);
|
new Requester(root).method("GET").to(getIssuesApiRoute(), this);
|
||||||
fetchedIssueDetails = true;
|
fetchedIssueDetails = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
|||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Commit detail inside a {@link GHPullRequest}.
|
* Commit detail inside a {@link GHPullRequest}.
|
||||||
@@ -144,6 +143,8 @@ public class GHPullRequestCommitDetail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public CommitPointer[] getParents() {
|
public CommitPointer[] getParents() {
|
||||||
return Arrays.copyOf(parents, parents.length);
|
CommitPointer[] newValue = new CommitPointer[parents.length];
|
||||||
|
System.arraycopy(parents, 0, newValue, 0, parents.length);
|
||||||
|
return newValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ public class GHPullRequestFileDetail {
|
|||||||
String raw_url;
|
String raw_url;
|
||||||
String contents_url;
|
String contents_url;
|
||||||
String patch;
|
String patch;
|
||||||
|
String previous_filename;
|
||||||
|
|
||||||
public String getSha() {
|
public String getSha() {
|
||||||
return sha;
|
return sha;
|
||||||
@@ -83,4 +84,9 @@ public class GHPullRequestFileDetail {
|
|||||||
public String getPatch() {
|
public String getPatch() {
|
||||||
return patch;
|
return patch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPreviousFilename()
|
||||||
|
{
|
||||||
|
return previous_filename;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.SHADOW_CAT;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists up pull requests with some filtering and sorting.
|
* Lists up pull requests with some filtering and sorting.
|
||||||
*
|
*
|
||||||
@@ -20,6 +22,9 @@ public class GHPullRequestQueryBuilder extends GHQueryBuilder<GHPullRequest> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GHPullRequestQueryBuilder head(String head) {
|
public GHPullRequestQueryBuilder head(String head) {
|
||||||
|
if (head != null && !head.contains(":")) {
|
||||||
|
head = repo.getOwnerName() + ":" + head;
|
||||||
|
}
|
||||||
req.with("head",head);
|
req.with("head",head);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -43,16 +48,11 @@ public class GHPullRequestQueryBuilder extends GHQueryBuilder<GHPullRequest> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PagedIterable<GHPullRequest> list() {
|
public PagedIterable<GHPullRequest> list() {
|
||||||
return new PagedIterable<GHPullRequest>() {
|
return req
|
||||||
public PagedIterator<GHPullRequest> _iterator(int pageSize) {
|
.withPreview(SHADOW_CAT)
|
||||||
return new PagedIterator<GHPullRequest>(req.asIterator(repo.getApiTailUrl("pulls"), GHPullRequest[].class, pageSize)) {
|
.asPagedIterable(
|
||||||
@Override
|
repo.getApiTailUrl("pulls"),
|
||||||
protected void wrapUp(GHPullRequest[] page) {
|
GHPullRequest[].class,
|
||||||
for (GHPullRequest pr : page)
|
item -> item.wrapUp(repo) );
|
||||||
pr.wrapUp(repo);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
157
src/main/java/org/kohsuke/github/GHPullRequestReview.java
Normal file
157
src/main/java/org/kohsuke/github/GHPullRequestReview.java
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017, CloudBees, Inc.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import javax.annotation.CheckForNull;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Review to a pull request.
|
||||||
|
*
|
||||||
|
* @see GHPullRequest#listReviews()
|
||||||
|
* @see GHPullRequestReviewBuilder
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_FIELD"}, justification = "JSON API")
|
||||||
|
public class GHPullRequestReview extends GHObject {
|
||||||
|
GHPullRequest owner;
|
||||||
|
|
||||||
|
private String body;
|
||||||
|
private GHUser user;
|
||||||
|
private String commit_id;
|
||||||
|
private GHPullRequestReviewState state;
|
||||||
|
private String submitted_at;
|
||||||
|
|
||||||
|
/*package*/ GHPullRequestReview wrapUp(GHPullRequest owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the pull request to which this review is associated.
|
||||||
|
*/
|
||||||
|
public GHPullRequest getParent() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The comment itself.
|
||||||
|
*/
|
||||||
|
public String getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the user who posted this review.
|
||||||
|
*/
|
||||||
|
public GHUser getUser() throws IOException {
|
||||||
|
return owner.root.getUser(user.getLogin());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCommitId() {
|
||||||
|
return commit_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@CheckForNull
|
||||||
|
public GHPullRequestReviewState getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL getHtmlUrl() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getApiRoute() {
|
||||||
|
return owner.getApiRoute()+"/reviews/"+id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When was this resource created?
|
||||||
|
*/
|
||||||
|
public Date getSubmittedAt() throws IOException {
|
||||||
|
return GitHub.parseDate(submitted_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Since this method does not exist, we forward this value.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Date getCreatedAt() throws IOException {
|
||||||
|
return getSubmittedAt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Former preview method that changed when it got public. Left here for backward compatibility.
|
||||||
|
* Use {@link #submit(String, GHPullRequestReviewEvent)}
|
||||||
|
*/
|
||||||
|
public void submit(String body, GHPullRequestReviewState state) throws IOException {
|
||||||
|
submit(body,state.toEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the comment.
|
||||||
|
*/
|
||||||
|
public void submit(String body, GHPullRequestReviewEvent event) throws IOException {
|
||||||
|
new Requester(owner.root).method("POST")
|
||||||
|
.with("body", body)
|
||||||
|
.with("event", event.action())
|
||||||
|
.to(getApiRoute()+"/events",this);
|
||||||
|
this.body = body;
|
||||||
|
this.state = event.toState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes this review.
|
||||||
|
*/
|
||||||
|
public void delete() throws IOException {
|
||||||
|
new Requester(owner.root).method("DELETE")
|
||||||
|
.to(getApiRoute());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dismisses this review.
|
||||||
|
*/
|
||||||
|
public void dismiss(String message) throws IOException {
|
||||||
|
new Requester(owner.root).method("PUT")
|
||||||
|
.with("message", message)
|
||||||
|
.to(getApiRoute()+"/dismissals");
|
||||||
|
state = GHPullRequestReviewState.DISMISSED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains all the review comments associated with this pull request review.
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHPullRequestReviewComment> listReviewComments() throws IOException {
|
||||||
|
return owner.root.retrieve()
|
||||||
|
.asPagedIterable(
|
||||||
|
getApiRoute() + "/comments",
|
||||||
|
GHPullRequestReviewComment[].class,
|
||||||
|
item -> item.wrapUp(owner) );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds up a creation of new {@link GHPullRequestReview}.
|
||||||
|
*
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
* @see GHPullRequest#createReview()
|
||||||
|
*/
|
||||||
|
public class GHPullRequestReviewBuilder {
|
||||||
|
private final GHPullRequest pr;
|
||||||
|
private final Requester builder;
|
||||||
|
private final List<DraftReviewComment> comments = new ArrayList<DraftReviewComment>();
|
||||||
|
|
||||||
|
/*package*/ GHPullRequestReviewBuilder(GHPullRequest pr) {
|
||||||
|
this.pr = pr;
|
||||||
|
this.builder = new Requester(pr.root);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public GHPullRequestReview createReview(@Nullable String commitId, String body, GHPullRequestReviewEvent event,
|
||||||
|
// List<GHPullRequestReviewComment> comments) throws IOException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SHA of the commit that needs a review. Not using the latest commit SHA may render your review comment outdated if a subsequent commit modifies the line you specify as the position. Defaults to the most recent commit in the pull request when you do not specify a value.
|
||||||
|
*/
|
||||||
|
public GHPullRequestReviewBuilder commitId(String commitId) {
|
||||||
|
builder.with("commit_id",commitId);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Required when using REQUEST_CHANGES or COMMENT for the event parameter. The body text of the pull request review.
|
||||||
|
*/
|
||||||
|
public GHPullRequestReviewBuilder body(String body) {
|
||||||
|
builder.with("body",body);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The review action you want to perform. The review actions include: APPROVE, REQUEST_CHANGES, or COMMENT.
|
||||||
|
* By leaving this blank, you set the review action state to PENDING,
|
||||||
|
* which means you will need to {@linkplain GHPullRequestReview#submit(String, GHPullRequestReviewEvent) submit the pull request review} when you are ready.
|
||||||
|
*/
|
||||||
|
public GHPullRequestReviewBuilder event(GHPullRequestReviewEvent event) {
|
||||||
|
builder.with("event",event.action());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param body The relative path to the file that necessitates a review comment.
|
||||||
|
* @param path The position in the diff where you want to add a review comment. Note this value is not the same as the line number in the file. For help finding the position value, read the note below.
|
||||||
|
* @param position Text of the review comment.
|
||||||
|
*/
|
||||||
|
public GHPullRequestReviewBuilder comment(String body, String path, int position) {
|
||||||
|
comments.add(new DraftReviewComment(body,path,position));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHPullRequestReview create() throws IOException {
|
||||||
|
return builder.method("POST")._with("comments",comments)
|
||||||
|
.to(pr.getApiRoute() + "/reviews", GHPullRequestReview.class)
|
||||||
|
.wrapUp(pr);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class DraftReviewComment {
|
||||||
|
private String body;
|
||||||
|
private String path;
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
DraftReviewComment(String body, String path, int position) {
|
||||||
|
this.body = body;
|
||||||
|
this.path = path;
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,6 +25,9 @@ package org.kohsuke.github;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import javax.annotation.CheckForNull;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Review comment to the pull request
|
* Review comment to the pull request
|
||||||
@@ -33,14 +36,28 @@ import java.net.URL;
|
|||||||
* @see GHPullRequest#listReviewComments()
|
* @see GHPullRequest#listReviewComments()
|
||||||
* @see GHPullRequest#createReviewComment(String, String, String, int)
|
* @see GHPullRequest#createReviewComment(String, String, String, int)
|
||||||
*/
|
*/
|
||||||
public class GHPullRequestReviewComment extends GHObject {
|
public class GHPullRequestReviewComment extends GHObject implements Reactable {
|
||||||
GHPullRequest owner;
|
GHPullRequest owner;
|
||||||
|
|
||||||
private String body;
|
private String body;
|
||||||
private GHUser user;
|
private GHUser user;
|
||||||
private String path;
|
private String path;
|
||||||
private int position;
|
private int position = -1;
|
||||||
private int originalPosition;
|
private int original_position = -1;
|
||||||
|
private long in_reply_to_id = -1L;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* You should be using {@link GHPullRequestReviewBuilder#comment(String, String, int)}
|
||||||
|
*/
|
||||||
|
public static GHPullRequestReviewComment draft(String body, String path, int position) {
|
||||||
|
GHPullRequestReviewComment result = new GHPullRequestReviewComment();
|
||||||
|
result.body = body;
|
||||||
|
result.path = path;
|
||||||
|
result.position = position;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/*package*/ GHPullRequestReviewComment wrapUp(GHPullRequest owner) {
|
/*package*/ GHPullRequestReviewComment wrapUp(GHPullRequest owner) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
@@ -72,12 +89,18 @@ public class GHPullRequestReviewComment extends GHObject {
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CheckForNull
|
||||||
public int getPosition() {
|
public int getPosition() {
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getOriginalPosition() {
|
public int getOriginalPosition() {
|
||||||
return originalPosition;
|
return original_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@CheckForNull
|
||||||
|
public long getInReplyToId() {
|
||||||
|
return in_reply_to_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -103,4 +126,33 @@ public class GHPullRequestReviewComment extends GHObject {
|
|||||||
public void delete() throws IOException {
|
public void delete() throws IOException {
|
||||||
new Requester(owner.root).method("DELETE").to(getApiRoute());
|
new Requester(owner.root).method("DELETE").to(getApiRoute());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new comment that replies to this comment.
|
||||||
|
*/
|
||||||
|
public GHPullRequestReviewComment reply(String body) throws IOException {
|
||||||
|
return new Requester(owner.root).method("POST")
|
||||||
|
.with("body", body)
|
||||||
|
.with("in_reply_to", getId())
|
||||||
|
.to(getApiRoute() + "/comments", GHPullRequestReviewComment.class)
|
||||||
|
.wrapUp(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHReaction createReaction(ReactionContent content) throws IOException {
|
||||||
|
return new Requester(owner.root)
|
||||||
|
.withPreview(SQUIRREL_GIRL)
|
||||||
|
.with("content", content.getContent())
|
||||||
|
.to(getApiRoute()+"/reactions", GHReaction.class).wrap(owner.root);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview @Deprecated
|
||||||
|
public PagedIterable<GHReaction> listReactions() {
|
||||||
|
return owner.root.retrieve()
|
||||||
|
.withPreview(SQUIRREL_GIRL)
|
||||||
|
.asPagedIterable(
|
||||||
|
getApiRoute() + "/reactions",
|
||||||
|
GHReaction[].class,
|
||||||
|
item -> item.wrap(owner.root) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* The MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Eric Maupin
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action to perform on {@link GHPullRequestReview}.
|
||||||
|
*/
|
||||||
|
public enum GHPullRequestReviewEvent {
|
||||||
|
PENDING,
|
||||||
|
APPROVE,
|
||||||
|
REQUEST_CHANGES,
|
||||||
|
COMMENT;
|
||||||
|
|
||||||
|
/*package*/ String action() {
|
||||||
|
return this==PENDING ? null : name();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a {@link GHPullRequestReview} is submitted with this event, it should transition to this state.
|
||||||
|
*/
|
||||||
|
/*package*/ GHPullRequestReviewState toState() {
|
||||||
|
switch (this) {
|
||||||
|
case PENDING: return GHPullRequestReviewState.PENDING;
|
||||||
|
case APPROVE: return GHPullRequestReviewState.APPROVED;
|
||||||
|
case REQUEST_CHANGES: return GHPullRequestReviewState.CHANGES_REQUESTED;
|
||||||
|
case COMMENT: return GHPullRequestReviewState.COMMENTED;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current state of {@link GHPullRequestReview}
|
||||||
|
*/
|
||||||
|
public enum GHPullRequestReviewState {
|
||||||
|
PENDING,
|
||||||
|
APPROVED,
|
||||||
|
CHANGES_REQUESTED,
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* This was the thing when this API was in preview, but it changed when it became public.
|
||||||
|
* Use {@link #CHANGES_REQUESTED}. Left here for compatibility.
|
||||||
|
*/
|
||||||
|
REQUEST_CHANGES,
|
||||||
|
COMMENTED,
|
||||||
|
DISMISSED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* This was an internal method accidentally exposed.
|
||||||
|
* Left here for compatibility.
|
||||||
|
*/
|
||||||
|
public String action() {
|
||||||
|
GHPullRequestReviewEvent e = toEvent();
|
||||||
|
return e==null ? null : e.action();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ GHPullRequestReviewEvent toEvent() {
|
||||||
|
switch (this) {
|
||||||
|
case PENDING: return GHPullRequestReviewEvent.PENDING;
|
||||||
|
case APPROVED: return GHPullRequestReviewEvent.APPROVE;
|
||||||
|
case CHANGES_REQUESTED: return GHPullRequestReviewEvent.REQUEST_CHANGES;
|
||||||
|
case REQUEST_CHANGES: return GHPullRequestReviewEvent.REQUEST_CHANGES;
|
||||||
|
case COMMENTED: return GHPullRequestReviewEvent.COMMENT;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
55
src/main/java/org/kohsuke/github/GHReaction.java
Normal file
55
src/main/java/org/kohsuke/github/GHReaction.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import static org.kohsuke.github.Previews.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reaction to issue, comment, PR, and so on.
|
||||||
|
*
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
* @see Reactable
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public class GHReaction extends GHObject {
|
||||||
|
private GitHub root;
|
||||||
|
|
||||||
|
private GHUser user;
|
||||||
|
private ReactionContent content;
|
||||||
|
|
||||||
|
/*package*/ GHReaction wrap(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
user.wrapUp(root);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The kind of reaction left.
|
||||||
|
*/
|
||||||
|
public ReactionContent getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User who left the reaction.
|
||||||
|
*/
|
||||||
|
public GHUser getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reaction has no HTML URL. Don't call this method.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public URL getHtmlUrl() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes this reaction.
|
||||||
|
*/
|
||||||
|
public void delete() throws IOException {
|
||||||
|
new Requester(root).method("DELETE").withPreview(SQUIRREL_GIRL).to("/reactions/"+id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ package org.kohsuke.github;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static java.lang.String.format;
|
import static java.lang.String.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Release in a github repository.
|
* Release in a github repository.
|
||||||
@@ -45,10 +46,12 @@ public class GHRelease extends GHObject {
|
|||||||
return draft;
|
return draft;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
* Use {@link #update()}
|
||||||
|
*/
|
||||||
public GHRelease setDraft(boolean draft) throws IOException {
|
public GHRelease setDraft(boolean draft) throws IOException {
|
||||||
edit("draft", draft);
|
return update().draft(draft).update();
|
||||||
this.draft = draft;
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public URL getHtmlUrl() {
|
public URL getHtmlUrl() {
|
||||||
@@ -121,16 +124,23 @@ public class GHRelease extends GHObject {
|
|||||||
* Java 7 or greater. Options for fixing this for earlier JVMs can be found here
|
* Java 7 or greater. Options for fixing this for earlier JVMs can be found here
|
||||||
* http://stackoverflow.com/questions/12361090/server-name-indication-sni-on-java but involve more complicated
|
* http://stackoverflow.com/questions/12361090/server-name-indication-sni-on-java but involve more complicated
|
||||||
* handling of the HTTP requests to github's API.
|
* handling of the HTTP requests to github's API.
|
||||||
*
|
*/
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public GHAsset uploadAsset(File file, String contentType) throws IOException {
|
public GHAsset uploadAsset(File file, String contentType) throws IOException {
|
||||||
|
FileInputStream s = new FileInputStream(file);
|
||||||
|
try {
|
||||||
|
return uploadAsset(file.getName(), s, contentType);
|
||||||
|
} finally {
|
||||||
|
s.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHAsset uploadAsset(String filename, InputStream stream, String contentType) throws IOException {
|
||||||
Requester builder = new Requester(owner.root);
|
Requester builder = new Requester(owner.root);
|
||||||
|
|
||||||
String url = format("https://uploads.github.com%s/releases/%d/assets?name=%s",
|
String url = format("https://uploads.github.com%s/releases/%d/assets?name=%s",
|
||||||
owner.getApiTailUrl(""), getId(), file.getName());
|
owner.getApiTailUrl(""), getId(), filename);
|
||||||
return builder.contentType(contentType)
|
return builder.contentType(contentType)
|
||||||
.with(new FileInputStream(file))
|
.with(stream)
|
||||||
.to(url, GHAsset.class).wrap(this);
|
.to(url, GHAsset.class).wrap(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,10 +161,10 @@ public class GHRelease extends GHObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Edit this release.
|
* Updates this release via a builder.
|
||||||
*/
|
*/
|
||||||
private void edit(String key, Object value) throws IOException {
|
public GHReleaseUpdater update() {
|
||||||
new Requester(root)._with(key, value).method("PATCH").to(owner.getApiTailUrl("releases/"+id));
|
return new GHReleaseUpdater(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getApiTailUrl(String end) {
|
private String getApiTailUrl(String end) {
|
||||||
|
|||||||
@@ -21,9 +21,7 @@ public class GHReleaseBuilder {
|
|||||||
* @param body The release notes body.
|
* @param body The release notes body.
|
||||||
*/
|
*/
|
||||||
public GHReleaseBuilder body(String body) {
|
public GHReleaseBuilder body(String body) {
|
||||||
if (body != null) {
|
builder.with("body", body);
|
||||||
builder.with("body", body);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,12 +31,9 @@ public class GHReleaseBuilder {
|
|||||||
*
|
*
|
||||||
* @param commitish Defaults to the repository’s default branch (usually "master"). Unused if the Git tag
|
* @param commitish Defaults to the repository’s default branch (usually "master"). Unused if the Git tag
|
||||||
* already exists.
|
* already exists.
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public GHReleaseBuilder commitish(String commitish) {
|
public GHReleaseBuilder commitish(String commitish) {
|
||||||
if (commitish != null) {
|
builder.with("target_commitish", commitish);
|
||||||
builder.with("target_commitish", commitish);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,9 +52,7 @@ public class GHReleaseBuilder {
|
|||||||
* @param name the name of the release
|
* @param name the name of the release
|
||||||
*/
|
*/
|
||||||
public GHReleaseBuilder name(String name) {
|
public GHReleaseBuilder name(String name) {
|
||||||
if (name != null) {
|
builder.with("name", name);
|
||||||
builder.with("name", name);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
81
src/main/java/org/kohsuke/github/GHReleaseUpdater.java
Normal file
81
src/main/java/org/kohsuke/github/GHReleaseUpdater.java
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifies {@link GHRelease}.
|
||||||
|
*
|
||||||
|
* @author Kohsuke Kawaguchi
|
||||||
|
* @see GHRelease#update()
|
||||||
|
*/
|
||||||
|
public class GHReleaseUpdater {
|
||||||
|
private final GHRelease base;
|
||||||
|
private final Requester builder;
|
||||||
|
|
||||||
|
GHReleaseUpdater(GHRelease base) {
|
||||||
|
this.base = base;
|
||||||
|
this.builder = new Requester(base.root);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHReleaseUpdater tag(String tag) {
|
||||||
|
builder.with("tag_name",tag);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param body The release notes body.
|
||||||
|
*/
|
||||||
|
public GHReleaseUpdater body(String body) {
|
||||||
|
builder.with("body", body);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the commitish value that determines where the Git tag is created from. Can be any branch or
|
||||||
|
* commit SHA.
|
||||||
|
*
|
||||||
|
* @param commitish Defaults to the repository’s default branch (usually "master"). Unused if the Git tag
|
||||||
|
* already exists.
|
||||||
|
*/
|
||||||
|
public GHReleaseUpdater commitish(String commitish) {
|
||||||
|
builder.with("target_commitish", commitish);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional.
|
||||||
|
*
|
||||||
|
* @param draft {@code true} to create a draft (unpublished) release, {@code false} to create a published one.
|
||||||
|
* Default is {@code false}.
|
||||||
|
*/
|
||||||
|
public GHReleaseUpdater draft(boolean draft) {
|
||||||
|
builder.with("draft", draft);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param name the name of the release
|
||||||
|
*/
|
||||||
|
public GHReleaseUpdater name(String name) {
|
||||||
|
builder.with("name", name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional
|
||||||
|
*
|
||||||
|
* @param prerelease {@code true} to identify the release as a prerelease. {@code false} to identify the release
|
||||||
|
* as a full release. Default is {@code false}.
|
||||||
|
*/
|
||||||
|
public GHReleaseUpdater prerelease(boolean prerelease) {
|
||||||
|
builder.with("prerelease", prerelease);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRelease update() throws IOException {
|
||||||
|
return builder
|
||||||
|
.method("PATCH")
|
||||||
|
.to(base.owner.getApiTailUrl("releases/"+base.id), GHRelease.class).wrap(base.owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository clone statistics.
|
||||||
|
*
|
||||||
|
* @see GHRepository#getCloneTraffic()
|
||||||
|
*/
|
||||||
|
public class GHRepositoryCloneTraffic extends GHRepositoryTraffic {
|
||||||
|
private List<DailyInfo> clones;
|
||||||
|
|
||||||
|
/*package*/ GHRepositoryCloneTraffic() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ GHRepositoryCloneTraffic(Integer count, Integer uniques, List<DailyInfo> clones) {
|
||||||
|
super(count, uniques);
|
||||||
|
this.clones = clones;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DailyInfo> getClones() {
|
||||||
|
return clones;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DailyInfo> getDailyInfo() {
|
||||||
|
return getClones();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DailyInfo extends GHRepositoryTraffic.DailyInfo {
|
||||||
|
/*package*/ DailyInfo() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ DailyInfo(String timestamp, int count, int uniques) {
|
||||||
|
super(timestamp, count, uniques);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search repositories.
|
* Search repositories.
|
||||||
*
|
*
|
||||||
@@ -57,6 +55,15 @@ public class GHRepositorySearchBuilder extends GHSearchBuilder<GHRepository> {
|
|||||||
return q("stars:"+v);
|
return q("stars:"+v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GHRepositorySearchBuilder topic(String v) {
|
||||||
|
return q("topic:"+v);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepositorySearchBuilder order(GHDirection v) {
|
||||||
|
req.with("order",v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public GHRepositorySearchBuilder sort(Sort sort) {
|
public GHRepositorySearchBuilder sort(Sort sort) {
|
||||||
req.with("sort",sort);
|
req.with("sort",sort);
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
22
src/main/java/org/kohsuke/github/GHRepositorySelection.java
Normal file
22
src/main/java/org/kohsuke/github/GHRepositorySelection.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App installation repository selection.
|
||||||
|
*
|
||||||
|
* @author Paulo Miguel Almeida
|
||||||
|
*
|
||||||
|
* @see GHAppInstallation
|
||||||
|
*/
|
||||||
|
public enum GHRepositorySelection {
|
||||||
|
SELECTED,
|
||||||
|
ALL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns GitHub's internal representation of this event.
|
||||||
|
*/
|
||||||
|
String symbol() {
|
||||||
|
return name().toLowerCase(Locale.ENGLISH);
|
||||||
|
}
|
||||||
|
}
|
||||||
433
src/main/java/org/kohsuke/github/GHRepositoryStatistics.java
Normal file
433
src/main/java/org/kohsuke/github/GHRepositoryStatistics.java
Normal file
@@ -0,0 +1,433 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Statistics for a GitHub repository.
|
||||||
|
*
|
||||||
|
* @author Martin van Zijl
|
||||||
|
*/
|
||||||
|
public class GHRepositoryStatistics {
|
||||||
|
|
||||||
|
private final GHRepository repo;
|
||||||
|
private final GitHub root;
|
||||||
|
|
||||||
|
private static final int MAX_WAIT_ITERATIONS = 3;
|
||||||
|
private static final int WAIT_SLEEP_INTERVAL = 5000;
|
||||||
|
|
||||||
|
public GHRepositoryStatistics(GHRepository repo) {
|
||||||
|
this.repo = repo;
|
||||||
|
this.root = repo.root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get contributors list with additions, deletions, and commit count. See
|
||||||
|
* https://developer.github.com/v3/repos/statistics/#get-contributors-list-with-additions-deletions-and-commit-counts
|
||||||
|
*/
|
||||||
|
public PagedIterable<ContributorStats> getContributorStats() throws IOException, InterruptedException {
|
||||||
|
return getContributorStats(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param waitTillReady Whether to sleep the thread if necessary until the
|
||||||
|
* statistics are ready. This is true by default.
|
||||||
|
*/
|
||||||
|
@Preview
|
||||||
|
@Deprecated
|
||||||
|
@SuppressWarnings("SleepWhileInLoop")
|
||||||
|
@SuppressFBWarnings(value = {"RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE"}, justification = "JSON API")
|
||||||
|
public PagedIterable<ContributorStats> getContributorStats(boolean waitTillReady) throws IOException, InterruptedException {
|
||||||
|
PagedIterable<GHRepositoryStatistics.ContributorStats> stats =
|
||||||
|
getContributorStatsImpl();
|
||||||
|
|
||||||
|
if (stats == null && waitTillReady) {
|
||||||
|
for (int i = 0; i < MAX_WAIT_ITERATIONS; i += 1) {
|
||||||
|
// Wait a few seconds and try again.
|
||||||
|
Thread.sleep(WAIT_SLEEP_INTERVAL);
|
||||||
|
stats = getContributorStatsImpl();
|
||||||
|
if (stats != null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This gets the actual statistics from the server. Returns null if they
|
||||||
|
* are still being cached.
|
||||||
|
*/
|
||||||
|
private PagedIterable<ContributorStats> getContributorStatsImpl() throws IOException {
|
||||||
|
return root.retrieve()
|
||||||
|
.asPagedIterable(
|
||||||
|
getApiTailUrl("contributors"),
|
||||||
|
ContributorStats[].class,
|
||||||
|
item -> item.wrapUp(root) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
|
||||||
|
"NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD"}, justification = "JSON API")
|
||||||
|
public static class ContributorStats extends GHObject {
|
||||||
|
/*package almost final*/ private GitHub root;
|
||||||
|
private GHUser author;
|
||||||
|
private int total;
|
||||||
|
private List<Week> weeks;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL getHtmlUrl() throws IOException {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitHub getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The author described by these statistics.
|
||||||
|
*/
|
||||||
|
public GHUser getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The total number of commits authored by the contributor.
|
||||||
|
*/
|
||||||
|
public int getTotal() {
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method to look up week with particular timestamp.
|
||||||
|
*
|
||||||
|
* @param timestamp The timestamp to look for.
|
||||||
|
* @return The week starting with the given timestamp. Throws an
|
||||||
|
* exception if it is not found.
|
||||||
|
* @throws NoSuchElementException
|
||||||
|
*/
|
||||||
|
public Week getWeek(long timestamp) throws NoSuchElementException {
|
||||||
|
// maybe store the weeks in a map to make this more efficient?
|
||||||
|
for (Week week : weeks) {
|
||||||
|
if (week.getWeekTimestamp() == timestamp) {
|
||||||
|
return week;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is safer than returning null
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The total number of commits authored by the contributor.
|
||||||
|
*/
|
||||||
|
public List<Week> getWeeks() {
|
||||||
|
return weeks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return author.getLogin() + " made " + String.valueOf(total)
|
||||||
|
+ " contributions over " + String.valueOf(weeks.size())
|
||||||
|
+ " weeks";
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
|
||||||
|
"NP_UNWRITTEN_FIELD", "URF_UNREAD_FIELD"}, justification = "JSON API")
|
||||||
|
public static class Week {
|
||||||
|
|
||||||
|
private long w;
|
||||||
|
private int a;
|
||||||
|
private int d;
|
||||||
|
private int c;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Start of the week, as a UNIX timestamp.
|
||||||
|
*/
|
||||||
|
public long getWeekTimestamp() {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The number of additions for the week.
|
||||||
|
*/
|
||||||
|
public int getNumberOfAdditions() {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The number of deletions for the week.
|
||||||
|
*/
|
||||||
|
public int getNumberOfDeletions() {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The number of commits for the week.
|
||||||
|
*/
|
||||||
|
public int getNumberOfCommits() {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("Week starting %d - Additions: %d, Deletions: %d, Commits: %d", w, a, d, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ ContributorStats wrapUp(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last year of commit activity data. See
|
||||||
|
* https://developer.github.com/v3/repos/statistics/#get-the-last-year-of-commit-activity-data
|
||||||
|
*/
|
||||||
|
public PagedIterable<CommitActivity> getCommitActivity() throws IOException {
|
||||||
|
return root.retrieve()
|
||||||
|
.asPagedIterable(
|
||||||
|
getApiTailUrl("commit_activity"),
|
||||||
|
CommitActivity[].class,
|
||||||
|
item -> item.wrapUp(root) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
|
||||||
|
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
|
||||||
|
public static class CommitActivity extends GHObject {
|
||||||
|
/*package almost final*/ private GitHub root;
|
||||||
|
private List<Integer> days;
|
||||||
|
private int total;
|
||||||
|
private long week;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The number of commits for each day of the week. 0 = Sunday, 1
|
||||||
|
* = Monday, etc.
|
||||||
|
*/
|
||||||
|
public List<Integer> getDays() {
|
||||||
|
return days;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The total number of commits for the week.
|
||||||
|
*/
|
||||||
|
public int getTotal() {
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The start of the week as a UNIX timestamp.
|
||||||
|
*/
|
||||||
|
public long getWeek() {
|
||||||
|
return week;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ CommitActivity wrapUp(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitHub getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL getHtmlUrl() throws IOException {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of additions and deletions per week.
|
||||||
|
* See https://developer.github.com/v3/repos/statistics/#get-the-number-of-additions-and-deletions-per-week
|
||||||
|
*/
|
||||||
|
public List<CodeFrequency> getCodeFrequency() throws IOException {
|
||||||
|
// Map to ArrayLists first, since there are no field names in the
|
||||||
|
// returned JSON.
|
||||||
|
try {
|
||||||
|
InputStream stream = root.retrieve().asStream(getApiTailUrl("code_frequency"));
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
TypeReference<ArrayList<ArrayList<Integer> > > typeRef =
|
||||||
|
new TypeReference<ArrayList< ArrayList<Integer> > >() {};
|
||||||
|
ArrayList<ArrayList <Integer> > list = mapper.readValue(stream, typeRef);
|
||||||
|
|
||||||
|
// Convert to proper objects.
|
||||||
|
ArrayList<CodeFrequency> returnList = new ArrayList<CodeFrequency>();
|
||||||
|
for(ArrayList<Integer> item: list)
|
||||||
|
{
|
||||||
|
CodeFrequency cf = new CodeFrequency(item);
|
||||||
|
returnList.add(cf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnList;
|
||||||
|
} catch (MismatchedInputException e) {
|
||||||
|
// This sometimes happens when retrieving code frequency statistics
|
||||||
|
// for a repository for the first time. It is probably still being
|
||||||
|
// generated, so return null.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CodeFrequency {
|
||||||
|
private int week;
|
||||||
|
private int additions;
|
||||||
|
private int deletions;
|
||||||
|
|
||||||
|
private CodeFrequency(ArrayList<Integer> item) {
|
||||||
|
week = item.get(0);
|
||||||
|
additions = item.get(1);
|
||||||
|
deletions = item.get(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The start of the week as a UNIX timestamp.
|
||||||
|
*/
|
||||||
|
public int getWeekTimestamp() {
|
||||||
|
return week;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The number of additions for the week.
|
||||||
|
*/
|
||||||
|
public long getAdditions() {
|
||||||
|
return additions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The number of deletions for the week.
|
||||||
|
* NOTE: This will be a NEGATIVE number.
|
||||||
|
*/
|
||||||
|
public long getDeletions() {
|
||||||
|
// TODO: Perhaps return Math.abs(deletions),
|
||||||
|
// since most developers may not expect a negative number.
|
||||||
|
return deletions;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Week starting " + getWeekTimestamp() + " has " + getAdditions() +
|
||||||
|
" additions and " + Math.abs(getDeletions()) + " deletions";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the weekly commit count for the repository owner and everyone else.
|
||||||
|
* See https://developer.github.com/v3/repos/statistics/#get-the-weekly-commit-count-for-the-repository-owner-and-everyone-else
|
||||||
|
*/
|
||||||
|
public Participation getParticipation() throws IOException {
|
||||||
|
return root.retrieve().to(getApiTailUrl("participation"), Participation.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Participation extends GHObject {
|
||||||
|
/*package almost final*/ private GitHub root;
|
||||||
|
private List<Integer> all;
|
||||||
|
private List<Integer> owner;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL getHtmlUrl() throws IOException {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitHub getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The list of commit counts for everyone combined, for the
|
||||||
|
* last 52 weeks.
|
||||||
|
*/
|
||||||
|
public List<Integer> getAllCommits() {
|
||||||
|
return all;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The list of commit counts for the owner, for the
|
||||||
|
* last 52 weeks.
|
||||||
|
*/
|
||||||
|
public List<Integer> getOwnerCommits() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ Participation wrapUp(GitHub root) {
|
||||||
|
this.root = root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of commits per hour in each day.
|
||||||
|
* See https://developer.github.com/v3/repos/statistics/#get-the-number-of-commits-per-hour-in-each-day
|
||||||
|
*/
|
||||||
|
public List<PunchCardItem> getPunchCard() throws IOException {
|
||||||
|
// Map to ArrayLists first, since there are no field names in the
|
||||||
|
// returned JSON.
|
||||||
|
InputStream stream = root.retrieve().asStream(getApiTailUrl("punch_card"));
|
||||||
|
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
TypeReference<ArrayList<ArrayList<Integer> > > typeRef =
|
||||||
|
new TypeReference<ArrayList< ArrayList<Integer> > >() {};
|
||||||
|
ArrayList<ArrayList <Integer> > list = mapper.readValue(stream, typeRef);
|
||||||
|
|
||||||
|
// Convert to proper objects.
|
||||||
|
ArrayList<PunchCardItem> returnList = new ArrayList<PunchCardItem>();
|
||||||
|
for(ArrayList<Integer> item: list) {
|
||||||
|
PunchCardItem pci = new PunchCardItem(item);
|
||||||
|
returnList.add(pci);
|
||||||
|
}
|
||||||
|
|
||||||
|
return returnList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PunchCardItem {
|
||||||
|
private int dayOfWeek;
|
||||||
|
private int hourOfDay;
|
||||||
|
private int numberOfCommits;
|
||||||
|
|
||||||
|
private PunchCardItem(ArrayList<Integer> item) {
|
||||||
|
dayOfWeek = item.get(0);
|
||||||
|
hourOfDay = item.get(1);
|
||||||
|
numberOfCommits = item.get(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The day of the week.
|
||||||
|
* 0 = Sunday, 1 = Monday, etc.
|
||||||
|
*/
|
||||||
|
public int getDayOfWeek() {
|
||||||
|
return dayOfWeek;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The hour of the day from 0 to 23.
|
||||||
|
*/
|
||||||
|
public long getHourOfDay() {
|
||||||
|
return hourOfDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The number of commits for the day and hour.
|
||||||
|
*/
|
||||||
|
public long getNumberOfCommits() {
|
||||||
|
return numberOfCommits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "Day " + getDayOfWeek() + " Hour " + getHourOfDay() + ": " +
|
||||||
|
getNumberOfCommits() + " commits";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String getApiTailUrl(String tail) {
|
||||||
|
return repo.getApiTailUrl("stats/" + tail);
|
||||||
|
}
|
||||||
|
}
|
||||||
54
src/main/java/org/kohsuke/github/GHRepositoryTraffic.java
Normal file
54
src/main/java/org/kohsuke/github/GHRepositoryTraffic.java
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class GHRepositoryTraffic implements TrafficInfo {
|
||||||
|
private int count;
|
||||||
|
private int uniques;
|
||||||
|
|
||||||
|
/*package*/ GHRepositoryTraffic() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ GHRepositoryTraffic(int count, int uniques) {
|
||||||
|
this.count = count;
|
||||||
|
this.uniques = uniques;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUniques() {
|
||||||
|
return uniques;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract List<? extends DailyInfo> getDailyInfo();
|
||||||
|
|
||||||
|
public static abstract class DailyInfo implements TrafficInfo {
|
||||||
|
private String timestamp;
|
||||||
|
private int count;
|
||||||
|
private int uniques;
|
||||||
|
|
||||||
|
public Date getTimestamp() {
|
||||||
|
return GitHub.parseDate(timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getCount() {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUniques() {
|
||||||
|
return uniques;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ DailyInfo() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ DailyInfo(String timestamp, Integer count, Integer uniques) {
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.count = count;
|
||||||
|
this.uniques = uniques;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repository view statistics.
|
||||||
|
*
|
||||||
|
* @see GHRepository#getViewTraffic()
|
||||||
|
*/
|
||||||
|
public class GHRepositoryViewTraffic extends GHRepositoryTraffic {
|
||||||
|
private List<DailyInfo> views;
|
||||||
|
|
||||||
|
/*package*/ GHRepositoryViewTraffic() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ GHRepositoryViewTraffic(int count, int uniques, List<DailyInfo> views) {
|
||||||
|
super(count, uniques);
|
||||||
|
this.views = views;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DailyInfo> getViews() {
|
||||||
|
return views;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DailyInfo> getDailyInfo() {
|
||||||
|
return getViews();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DailyInfo extends GHRepositoryTraffic.DailyInfo {
|
||||||
|
/*package*/ DailyInfo() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*package*/ DailyInfo(String timestamp, int count, int uniques) {
|
||||||
|
super(timestamp, count, uniques);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|||||||
51
src/main/java/org/kohsuke/github/GHStargazer.java
Normal file
51
src/main/java/org/kohsuke/github/GHStargazer.java
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A stargazer at a repository on GitHub.
|
||||||
|
*
|
||||||
|
* @author noctarius
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_FIELD", "NP_UNWRITTEN_FIELD"}, justification = "JSON API")
|
||||||
|
public class GHStargazer {
|
||||||
|
|
||||||
|
private GHRepository repository;
|
||||||
|
private String starred_at;
|
||||||
|
private GHUser user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the repository that is stargazed
|
||||||
|
*
|
||||||
|
* @return the starred repository
|
||||||
|
*/
|
||||||
|
public GHRepository getRepository() {
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the date when the repository was starred, however old stars before
|
||||||
|
* August 2012, will all show the date the API was changed to support starred_at.
|
||||||
|
*
|
||||||
|
* @return the date the stargazer was added
|
||||||
|
*/
|
||||||
|
public Date getStarredAt() {
|
||||||
|
return GitHub.parseDate(starred_at);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the user that starred the repository
|
||||||
|
*
|
||||||
|
* @return the stargazer user
|
||||||
|
*/
|
||||||
|
public GHUser getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wrapUp(GHRepository repository) {
|
||||||
|
this.repository = repository;
|
||||||
|
user.wrapUp(repository.root);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,7 +49,7 @@ public class GHSubscription {
|
|||||||
* Removes this subscription.
|
* Removes this subscription.
|
||||||
*/
|
*/
|
||||||
public void delete() throws IOException {
|
public void delete() throws IOException {
|
||||||
new Requester(root).method("DELETE").to(url);
|
new Requester(root).method("DELETE").to(repo.getApiTailUrl("subscription"));
|
||||||
}
|
}
|
||||||
|
|
||||||
GHSubscription wrapUp(GHRepository repo) {
|
GHSubscription wrapUp(GHRepository repo) {
|
||||||
|
|||||||
60
src/main/java/org/kohsuke/github/GHTagObject.java
Normal file
60
src/main/java/org/kohsuke/github/GHTagObject.java
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an annotated tag in a {@link GHRepository}
|
||||||
|
*
|
||||||
|
* @see GHRepository#getTagObject(String)
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings(value = {"UWF_UNWRITTEN_PUBLIC_OR_PROTECTED_FIELD", "UWF_UNWRITTEN_FIELD",
|
||||||
|
"NP_UNWRITTEN_FIELD"}, justification = "JSON API")
|
||||||
|
public class GHTagObject {
|
||||||
|
private GHRepository owner;
|
||||||
|
private GitHub root;
|
||||||
|
|
||||||
|
private String tag;
|
||||||
|
private String sha;
|
||||||
|
private String url;
|
||||||
|
private String message;
|
||||||
|
private GitUser tagger;
|
||||||
|
private GHRef.GHObject object;
|
||||||
|
|
||||||
|
/*package*/ GHTagObject wrap(GHRepository owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
this.root = owner.root;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRepository getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitHub getRoot() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTag() {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSha() {
|
||||||
|
return sha;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitUser getTagger() {
|
||||||
|
return tagger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHRef.GHObject getObject() {
|
||||||
|
return object;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/main/java/org/kohsuke/github/GHTargetType.java
Normal file
24
src/main/java/org/kohsuke/github/GHTargetType.java
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* App installation target type.
|
||||||
|
*
|
||||||
|
* @author Paulo Miguel Almeida
|
||||||
|
*
|
||||||
|
* @see GHAppInstallation
|
||||||
|
*/
|
||||||
|
public enum GHTargetType {
|
||||||
|
ORGANIZATION,
|
||||||
|
USER;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns GitHub's internal representation of this event.
|
||||||
|
*/
|
||||||
|
String symbol() {
|
||||||
|
return StringUtils.capitalize(name().toLowerCase(Locale.ENGLISH));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,15 +11,28 @@ import java.util.TreeMap;
|
|||||||
*
|
*
|
||||||
* @author Kohsuke Kawaguchi
|
* @author Kohsuke Kawaguchi
|
||||||
*/
|
*/
|
||||||
public class GHTeam {
|
public class GHTeam implements Refreshable {
|
||||||
private String name,permission;
|
private String name,permission,slug,description;
|
||||||
private int id;
|
private int id;
|
||||||
private GHOrganization organization; // populated by GET /user/teams where Teams+Orgs are returned together
|
private GHOrganization organization; // populated by GET /user/teams where Teams+Orgs are returned together
|
||||||
|
|
||||||
protected /*final*/ GHOrganization org;
|
protected /*final*/ GitHub root;
|
||||||
|
|
||||||
|
/** Member's role in a team */
|
||||||
|
public enum Role {
|
||||||
|
/**
|
||||||
|
* A normal member of the team
|
||||||
|
*/
|
||||||
|
MEMBER,
|
||||||
|
/**
|
||||||
|
* Able to add/remove other team members, promote other team members to team maintainer, and edit the team's name and description.
|
||||||
|
*/
|
||||||
|
MAINTAINER
|
||||||
|
}
|
||||||
|
|
||||||
/*package*/ GHTeam wrapUp(GHOrganization owner) {
|
/*package*/ GHTeam wrapUp(GHOrganization owner) {
|
||||||
this.org = owner;
|
this.organization = owner;
|
||||||
|
this.root = owner.root;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,6 +48,13 @@ public class GHTeam {
|
|||||||
return teams;
|
return teams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*package*/ static GHTeam[] wrapUp(GHTeam[] teams, GHPullRequest owner) {
|
||||||
|
for (GHTeam t : teams) {
|
||||||
|
t.root = owner.root;
|
||||||
|
}
|
||||||
|
return teams;
|
||||||
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@@ -43,6 +63,20 @@ public class GHTeam {
|
|||||||
return permission;
|
return permission;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getSlug() {
|
||||||
|
return slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) throws IOException {
|
||||||
|
root.retrieve().method("PATCH")
|
||||||
|
.with("description", description)
|
||||||
|
.to(api(""));
|
||||||
|
}
|
||||||
|
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@@ -51,16 +85,11 @@ public class GHTeam {
|
|||||||
* Retrieves the current members.
|
* Retrieves the current members.
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHUser> listMembers() throws IOException {
|
public PagedIterable<GHUser> listMembers() throws IOException {
|
||||||
return new PagedIterable<GHUser>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHUser> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHUser>(org.root.retrieve().asIterator(api("/members"), GHUser[].class, pageSize)) {
|
api("/members"),
|
||||||
@Override
|
GHUser[].class,
|
||||||
protected void wrapUp(GHUser[] page) {
|
item -> item.wrapUp(root) );
|
||||||
GHUser.wrap(page, org.root);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<GHUser> getMembers() throws IOException {
|
public Set<GHUser> getMembers() throws IOException {
|
||||||
@@ -72,7 +101,7 @@ public class GHTeam {
|
|||||||
*/
|
*/
|
||||||
public boolean hasMember(GHUser user) {
|
public boolean hasMember(GHUser user) {
|
||||||
try {
|
try {
|
||||||
org.root.retrieve().to("/teams/" + id + "/members/" + user.getLogin());
|
root.retrieve().to("/teams/" + id + "/members/" + user.getLogin());
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException ignore) {
|
} catch (IOException ignore) {
|
||||||
return false;
|
return false;
|
||||||
@@ -88,17 +117,11 @@ public class GHTeam {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PagedIterable<GHRepository> listRepositories() {
|
public PagedIterable<GHRepository> listRepositories() {
|
||||||
return new PagedIterable<GHRepository>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHRepository> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHRepository>(org.root.retrieve().asIterator(api("/repos"), GHRepository[].class, pageSize)) {
|
api("/repos"),
|
||||||
@Override
|
GHRepository[].class,
|
||||||
protected void wrapUp(GHRepository[] page) {
|
item -> item.wrap(root) );
|
||||||
for (GHRepository r : page)
|
|
||||||
r.wrap(org.root);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,29 +132,64 @@ public class GHTeam {
|
|||||||
* @since 1.59
|
* @since 1.59
|
||||||
*/
|
*/
|
||||||
public void add(GHUser u) throws IOException {
|
public void add(GHUser u) throws IOException {
|
||||||
org.root.retrieve().method("PUT").to(api("/memberships/" + u.getLogin()), null);
|
root.retrieve().method("PUT").to(api("/memberships/" + u.getLogin()), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a member to the team
|
||||||
|
*
|
||||||
|
* The user will be invited to the organization if required.
|
||||||
|
*
|
||||||
|
* @param user github user
|
||||||
|
* @param role role for the new member
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void add(GHUser user, Role role) throws IOException {
|
||||||
|
root.retrieve().method("PUT")
|
||||||
|
.with("role", role)
|
||||||
|
.to(api("/memberships/" + user.getLogin()), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a member to the team.
|
* Removes a member to the team.
|
||||||
*/
|
*/
|
||||||
public void remove(GHUser u) throws IOException {
|
public void remove(GHUser u) throws IOException {
|
||||||
org.root.retrieve().method("DELETE").to(api("/members/" + u.getLogin()), null);
|
root.retrieve().method("DELETE").to(api("/members/" + u.getLogin()), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(GHRepository r) throws IOException {
|
public void add(GHRepository r) throws IOException {
|
||||||
org.root.retrieve().method("PUT").to(api("/repos/" + r.getOwnerName() + '/' + r.getName()), null);
|
add(r,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(GHRepository r, GHOrganization.Permission permission) throws IOException {
|
||||||
|
root.retrieve().method("PUT")
|
||||||
|
.with("permission", permission)
|
||||||
|
.to(api("/repos/" + r.getOwnerName() + '/' + r.getName()), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(GHRepository r) throws IOException {
|
public void remove(GHRepository r) throws IOException {
|
||||||
org.root.retrieve().method("DELETE").to(api("/repos/" + r.getOwnerName() + '/' + r.getName()), null);
|
root.retrieve().method("DELETE").to(api("/repos/" + r.getOwnerName() + '/' + r.getName()), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes this team.
|
||||||
|
*/
|
||||||
|
public void delete() throws IOException {
|
||||||
|
root.retrieve().method("DELETE").to(api(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
private String api(String tail) {
|
private String api(String tail) {
|
||||||
return "/teams/"+id+tail;
|
return "/teams/" + id + tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GHOrganization getOrganization() {
|
public GHOrganization getOrganization() throws IOException {
|
||||||
return org;
|
refresh(organization);
|
||||||
|
return organization;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refresh() throws IOException {
|
||||||
|
root.retrieve().to(api(""), this).wrapUp(root);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|||||||
@@ -10,10 +10,12 @@ import java.util.List;
|
|||||||
* https://developer.github.com/v3/git/trees/
|
* https://developer.github.com/v3/git/trees/
|
||||||
*
|
*
|
||||||
* @author Daniel Teixeira - https://github.com/ddtxra
|
* @author Daniel Teixeira - https://github.com/ddtxra
|
||||||
|
* @see GHCommit#getTree()
|
||||||
* @see GHRepository#getTree(String)
|
* @see GHRepository#getTree(String)
|
||||||
|
* @see GHTreeEntry#asTree()
|
||||||
*/
|
*/
|
||||||
public class GHTree {
|
public class GHTree {
|
||||||
/* package almost final */GitHub root;
|
/* package almost final */GHRepository repo;
|
||||||
|
|
||||||
private boolean truncated;
|
private boolean truncated;
|
||||||
private String sha, url;
|
private String sha, url;
|
||||||
@@ -28,12 +30,24 @@ public class GHTree {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an array of entries of the trees
|
* Return an array of entries of the trees
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public List<GHTreeEntry> getTree() {
|
public List<GHTreeEntry> getTree() {
|
||||||
return Collections.unmodifiableList(Arrays.asList(tree));
|
return Collections.unmodifiableList(Arrays.asList(tree));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a tree entry by its name.
|
||||||
|
*
|
||||||
|
* IOW, find a directory entry by a file name.
|
||||||
|
*/
|
||||||
|
public GHTreeEntry getEntry(String path) {
|
||||||
|
for (GHTreeEntry e : tree) {
|
||||||
|
if (e.getPath().equals(path))
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the number of items in the tree array exceeded the GitHub maximum limit.
|
* Returns true if the number of items in the tree array exceeded the GitHub maximum limit.
|
||||||
* @return true true if the number of items in the tree array exceeded the GitHub maximum limit otherwise false.
|
* @return true true if the number of items in the tree array exceeded the GitHub maximum limit otherwise false.
|
||||||
@@ -50,8 +64,11 @@ public class GHTree {
|
|||||||
return GitHub.parseURL(url);
|
return GitHub.parseURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */GHTree wrap(GitHub root) {
|
/* package */GHTree wrap(GHRepository repo) {
|
||||||
this.root = root;
|
this.repo = repo;
|
||||||
|
for (GHTreeEntry e : tree) {
|
||||||
|
e.tree = this;
|
||||||
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
90
src/main/java/org/kohsuke/github/GHTreeBuilder.java
Normal file
90
src/main/java/org/kohsuke/github/GHTreeBuilder.java
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builder pattern for creating a new tree.
|
||||||
|
* Based on https://developer.github.com/v3/git/trees/#create-a-tree
|
||||||
|
*/
|
||||||
|
public class GHTreeBuilder {
|
||||||
|
private final GHRepository repo;
|
||||||
|
private final Requester req;
|
||||||
|
|
||||||
|
private final List<TreeEntry> treeEntries = new ArrayList<TreeEntry>();
|
||||||
|
|
||||||
|
@SuppressFBWarnings("URF_UNREAD_FIELD")
|
||||||
|
private static final class TreeEntry {
|
||||||
|
private final String path;
|
||||||
|
private final String mode;
|
||||||
|
private final String type;
|
||||||
|
private String sha;
|
||||||
|
private String content;
|
||||||
|
|
||||||
|
private TreeEntry(String path, String mode, String type) {
|
||||||
|
this.path = path;
|
||||||
|
this.mode = mode;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GHTreeBuilder(GHRepository repo) {
|
||||||
|
this.repo = repo;
|
||||||
|
req = new Requester(repo.root);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param baseTree the SHA of tree you want to update with new data
|
||||||
|
*/
|
||||||
|
public GHTreeBuilder baseTree(String baseTree) {
|
||||||
|
req.with("base_tree", baseTree);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new entry to the tree.
|
||||||
|
* Exactly one of the parameters {@code sha} and {@code content} must be non-null.
|
||||||
|
*/
|
||||||
|
public GHTreeBuilder entry(String path, String mode, String type, String sha, String content) {
|
||||||
|
TreeEntry entry = new TreeEntry(path, mode, type);
|
||||||
|
entry.sha = sha;
|
||||||
|
entry.content = content;
|
||||||
|
treeEntries.add(entry);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialized version of {@link #entry(String, String, String, String, String)} for adding an existing blob referred by its SHA.
|
||||||
|
*/
|
||||||
|
public GHTreeBuilder shaEntry(String path, String sha, boolean executable) {
|
||||||
|
TreeEntry entry = new TreeEntry(path, executable ? "100755" : "100644", "blob");
|
||||||
|
entry.sha = sha;
|
||||||
|
treeEntries.add(entry);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specialized version of {@link #entry(String, String, String, String, String)} for adding a text file with the specified {@code content}.
|
||||||
|
*/
|
||||||
|
public GHTreeBuilder textEntry(String path, String content, boolean executable) {
|
||||||
|
TreeEntry entry = new TreeEntry(path, executable ? "100755" : "100644", "blob");
|
||||||
|
entry.content = content;
|
||||||
|
treeEntries.add(entry);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getApiTail() {
|
||||||
|
return String.format("/repos/%s/%s/git/trees", repo.getOwnerName(), repo.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a tree based on the parameters specified thus far.
|
||||||
|
*/
|
||||||
|
public GHTree create() throws IOException {
|
||||||
|
req._with("tree", treeEntries);
|
||||||
|
return req.method("POST").to(getApiTail(), GHTree.class).wrap(repo);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -10,6 +12,8 @@ import java.net.URL;
|
|||||||
* @see GHTree
|
* @see GHTree
|
||||||
*/
|
*/
|
||||||
public class GHTreeEntry {
|
public class GHTreeEntry {
|
||||||
|
/* package almost final */GHTree tree;
|
||||||
|
|
||||||
private String path, mode, type, sha, url;
|
private String path, mode, type, sha, url;
|
||||||
private long size;
|
private long size;
|
||||||
|
|
||||||
@@ -44,7 +48,7 @@ public class GHTreeEntry {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the type such as:
|
* Gets the type such as:
|
||||||
* "blob"
|
* "blob", "tree", etc.
|
||||||
*
|
*
|
||||||
* @return The type
|
* @return The type
|
||||||
*/
|
*/
|
||||||
@@ -68,4 +72,37 @@ public class GHTreeEntry {
|
|||||||
public URL getUrl() {
|
public URL getUrl() {
|
||||||
return GitHub.parseURL(url);
|
return GitHub.parseURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this tree entry represents a file, then return its information.
|
||||||
|
* Otherwise null.
|
||||||
|
*/
|
||||||
|
public GHBlob asBlob() throws IOException {
|
||||||
|
if (type.equals("blob"))
|
||||||
|
return tree.repo.getBlob(sha);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this tree entry represents a file, then return its content.
|
||||||
|
* Otherwise null.
|
||||||
|
*/
|
||||||
|
public InputStream readAsBlob() throws IOException {
|
||||||
|
if (type.equals("blob"))
|
||||||
|
return tree.repo.readBlob(sha);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this tree entry represents a directory, then return it.
|
||||||
|
* Otherwise null.
|
||||||
|
*/
|
||||||
|
public GHTree asTree() throws IOException {
|
||||||
|
if (type.equals("tree"))
|
||||||
|
return tree.repo.getTree(sha);
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,8 +26,7 @@ package org.kohsuke.github;
|
|||||||
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashSet;
|
import java.util.*;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an user of GitHub.
|
* Represents an user of GitHub.
|
||||||
@@ -36,6 +35,10 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public class GHUser extends GHPerson {
|
public class GHUser extends GHPerson {
|
||||||
|
|
||||||
|
public List<GHKey> getKeys() throws IOException {
|
||||||
|
return Collections.unmodifiableList(Arrays.asList(root.retrieve().to(getApiTailUrl("keys"), GHKey[].class)));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Follow this user.
|
* Follow this user.
|
||||||
*/
|
*/
|
||||||
@@ -81,15 +84,11 @@ public class GHUser extends GHPerson {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PagedIterable<GHUser> listUser(final String suffix) {
|
private PagedIterable<GHUser> listUser(final String suffix) {
|
||||||
return new PagedIterable<GHUser>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHUser> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHUser>(root.retrieve().asIterator(getApiTailUrl(suffix), GHUser[].class, pageSize)) {
|
getApiTailUrl(suffix),
|
||||||
protected void wrapUp(GHUser[] page) {
|
GHUser[].class,
|
||||||
GHUser.wrap(page,root);
|
item -> item.wrapUp(root) );
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,16 +108,11 @@ public class GHUser extends GHPerson {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PagedIterable<GHRepository> listRepositories(final String suffix) {
|
private PagedIterable<GHRepository> listRepositories(final String suffix) {
|
||||||
return new PagedIterable<GHRepository>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHRepository> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHRepository>(root.retrieve().asIterator(getApiTailUrl(suffix), GHRepository[].class, pageSize)) {
|
getApiTailUrl(suffix),
|
||||||
protected void wrapUp(GHRepository[] page) {
|
GHRepository[].class,
|
||||||
for (GHRepository c : page)
|
item -> item.wrap(root) );
|
||||||
c.wrap(root);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -166,39 +160,22 @@ public class GHUser extends GHPerson {
|
|||||||
* Lists events performed by a user (this includes private events if the caller is authenticated.
|
* Lists events performed by a user (this includes private events if the caller is authenticated.
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHEventInfo> listEvents() throws IOException {
|
public PagedIterable<GHEventInfo> listEvents() throws IOException {
|
||||||
return new PagedIterable<GHEventInfo>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHEventInfo> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHEventInfo>(root.retrieve().asIterator(String.format("/users/%s/events", login), GHEventInfo[].class, pageSize)) {
|
String.format("/users/%s/events", login),
|
||||||
@Override
|
GHEventInfo[].class,
|
||||||
protected void wrapUp(GHEventInfo[] page) {
|
item -> item.wrapUp(root) );
|
||||||
for (GHEventInfo c : page)
|
|
||||||
c.wrapUp(root);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lists Gists created by this user.
|
* Lists Gists created by this user.
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHGist> listGists() throws IOException {
|
public PagedIterable<GHGist> listGists() throws IOException {
|
||||||
return new PagedIterable<GHGist>() {
|
return root.retrieve()
|
||||||
public PagedIterator<GHGist> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHGist>(root.retrieve().asIterator(String.format("/users/%s/gists", login), GHGist[].class, pageSize)) {
|
String.format("/users/%s/gists", login),
|
||||||
@Override
|
GHGist[].class,
|
||||||
protected void wrapUp(GHGist[] page) {
|
item -> item.wrapUp(GHUser.this) );
|
||||||
for (GHGist c : page)
|
|
||||||
c.wrapUp(GHUser.this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "User:"+login;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -219,4 +196,9 @@ public class GHUser extends GHPerson {
|
|||||||
if (tail.length()>0 && !tail.startsWith("/")) tail='/'+tail;
|
if (tail.length()>0 && !tail.startsWith("/")) tail='/'+tail;
|
||||||
return "/users/" + login + tail;
|
return "/users/" + login + tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*package*/ GHUser wrapUp(GitHub root) {
|
||||||
|
super.wrapUp(root);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search users.
|
* Search users.
|
||||||
*
|
*
|
||||||
@@ -49,6 +47,11 @@ public class GHUserSearchBuilder extends GHSearchBuilder<GHUser> {
|
|||||||
return q("followers:"+v);
|
return q("followers:"+v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GHUserSearchBuilder order(GHDirection v) {
|
||||||
|
req.with("order",v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public GHUserSearchBuilder sort(Sort sort) {
|
public GHUserSearchBuilder sort(Sort sort) {
|
||||||
req.with("sort",sort);
|
req.with("sort",sort);
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -23,38 +23,34 @@
|
|||||||
*/
|
*/
|
||||||
package org.kohsuke.github;
|
package org.kohsuke.github;
|
||||||
|
|
||||||
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
|
import com.fasterxml.jackson.databind.MapperFeature;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.introspect.VisibilityChecker.Std;
|
||||||
|
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
||||||
|
import org.apache.commons.codec.Charsets;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import javax.annotation.CheckForNull;
|
||||||
import java.io.FileNotFoundException;
|
import javax.annotation.Nonnull;
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.InputStreamReader;
|
import java.net.HttpURLConnection;
|
||||||
import java.io.Reader;
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.Date;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.HashMap;
|
import java.util.logging.Logger;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.commons.codec.Charsets;
|
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE;
|
||||||
|
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import static java.util.logging.Level.FINE;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import static org.kohsuke.github.Previews.INERTIA;
|
||||||
import com.fasterxml.jackson.databind.introspect.VisibilityChecker.Std;
|
import static org.kohsuke.github.Previews.MACHINE_MAN;
|
||||||
import com.infradna.tool.bridge_method_injector.WithBridgeMethods;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root of the GitHub API.
|
* Root of the GitHub API.
|
||||||
@@ -75,15 +71,21 @@ public class GitHub {
|
|||||||
*/
|
*/
|
||||||
/*package*/ final String encodedAuthorization;
|
/*package*/ final String encodedAuthorization;
|
||||||
|
|
||||||
private final Map<String,GHUser> users = new Hashtable<String, GHUser>();
|
private final ConcurrentMap<String,GHUser> users;
|
||||||
private final Map<String,GHOrganization> orgs = new Hashtable<String, GHOrganization>();
|
private final ConcurrentMap<String,GHOrganization> orgs;
|
||||||
|
// Cache of myself object.
|
||||||
|
private GHMyself myself;
|
||||||
private final String apiUrl;
|
private final String apiUrl;
|
||||||
|
|
||||||
/*package*/ final RateLimitHandler rateLimitHandler;
|
/*package*/ final RateLimitHandler rateLimitHandler;
|
||||||
|
/*package*/ final AbuseLimitHandler abuseLimitHandler;
|
||||||
|
|
||||||
private HttpConnector connector = HttpConnector.DEFAULT;
|
private HttpConnector connector = HttpConnector.DEFAULT;
|
||||||
|
|
||||||
|
private final Object headerRateLimitLock = new Object();
|
||||||
|
private GHRateLimit headerRateLimit = null;
|
||||||
|
private volatile GHRateLimit rateLimit = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a client API root object.
|
* Creates a client API root object.
|
||||||
*
|
*
|
||||||
@@ -92,7 +94,7 @@ public class GitHub {
|
|||||||
* to represent different ways of authentication.
|
* to represent different ways of authentication.
|
||||||
*
|
*
|
||||||
* <dl>
|
* <dl>
|
||||||
* <dt>Loging anonymously
|
* <dt>Log in anonymously
|
||||||
* <dd>Leave all three parameters null and you will be making HTTP requests without any authentication.
|
* <dd>Leave all three parameters null and you will be making HTTP requests without any authentication.
|
||||||
*
|
*
|
||||||
* <dt>Log in with password
|
* <dt>Log in with password
|
||||||
@@ -103,15 +105,21 @@ public class GitHub {
|
|||||||
* <dd>Specify oauthAccessToken, and optionally specify the login. Leave password null.
|
* <dd>Specify oauthAccessToken, and optionally specify the login. Leave password null.
|
||||||
* This will send OAuth token to the GitHub API. If the login parameter is null,
|
* This will send OAuth token to the GitHub API. If the login parameter is null,
|
||||||
* The constructor makes an API call to figure out the user name that owns the token.
|
* The constructor makes an API call to figure out the user name that owns the token.
|
||||||
|
*
|
||||||
|
* <dt>Log in with JWT token
|
||||||
|
* <dd>Specify jwtToken. Leave password null.
|
||||||
|
* This will send JWT token to the GitHub API via the Authorization HTTP header.
|
||||||
|
* Please note that only operations in which permissions have been previously configured and accepted during
|
||||||
|
* the GitHub App will be executed successfully.
|
||||||
* </dl>
|
* </dl>
|
||||||
*
|
*
|
||||||
* @param apiUrl
|
* @param apiUrl
|
||||||
* The URL of GitHub (or GitHub enterprise) API endpoint, such as "https://api.github.com" or
|
* The URL of GitHub (or GitHub enterprise) API endpoint, such as "https://api.github.com" or
|
||||||
* "http://ghe.acme.com/api/v3". Note that GitHub Enterprise has <tt>/api/v3</tt> in the URL.
|
* "http://ghe.acme.com/api/v3". Note that GitHub Enterprise has <code>/api/v3</code> in the URL.
|
||||||
* For historical reasons, this parameter still accepts the bare domain name, but that's considered deprecated.
|
* For historical reasons, this parameter still accepts the bare domain name, but that's considered deprecated.
|
||||||
* Password is also considered deprecated as it is no longer required for api usage.
|
* Password is also considered deprecated as it is no longer required for api usage.
|
||||||
* @param login
|
* @param login
|
||||||
* The use ID on GitHub that you are logging in as. Can be omitted if the OAuth token is
|
* The user ID on GitHub that you are logging in as. Can be omitted if the OAuth token is
|
||||||
* provided or if logging in anonymously. Specifying this would save one API call.
|
* provided or if logging in anonymously. Specifying this would save one API call.
|
||||||
* @param oauthAccessToken
|
* @param oauthAccessToken
|
||||||
* Secret OAuth token.
|
* Secret OAuth token.
|
||||||
@@ -120,7 +128,7 @@ public class GitHub {
|
|||||||
* @param connector
|
* @param connector
|
||||||
* HttpConnector to use. Pass null to use default connector.
|
* HttpConnector to use. Pass null to use default connector.
|
||||||
*/
|
*/
|
||||||
/* package */ GitHub(String apiUrl, String login, String oauthAccessToken, String password, HttpConnector connector, RateLimitHandler rateLimitHandler) throws IOException {
|
/* package */ GitHub(String apiUrl, String login, String oauthAccessToken, String jwtToken, String password, HttpConnector connector, RateLimitHandler rateLimitHandler, AbuseLimitHandler abuseLimitHandler) throws IOException {
|
||||||
if (apiUrl.endsWith("/")) apiUrl = apiUrl.substring(0, apiUrl.length()-1); // normalize
|
if (apiUrl.endsWith("/")) apiUrl = apiUrl.substring(0, apiUrl.length()-1); // normalize
|
||||||
this.apiUrl = apiUrl;
|
this.apiUrl = apiUrl;
|
||||||
if (null != connector) this.connector = connector;
|
if (null != connector) this.connector = connector;
|
||||||
@@ -128,18 +136,23 @@ public class GitHub {
|
|||||||
if (oauthAccessToken!=null) {
|
if (oauthAccessToken!=null) {
|
||||||
encodedAuthorization = "token "+oauthAccessToken;
|
encodedAuthorization = "token "+oauthAccessToken;
|
||||||
} else {
|
} else {
|
||||||
if (password!=null) {
|
if(jwtToken!=null){
|
||||||
|
encodedAuthorization = "Bearer "+jwtToken;
|
||||||
|
}else if (password!=null) {
|
||||||
String authorization = (login + ':' + password);
|
String authorization = (login + ':' + password);
|
||||||
Charset charset = Charsets.UTF_8;
|
String charsetName = Charsets.UTF_8.name();
|
||||||
encodedAuthorization = "Basic "+new String(Base64.encodeBase64(authorization.getBytes(charset)), charset);
|
encodedAuthorization = "Basic "+new String(Base64.encodeBase64(authorization.getBytes(charsetName)), charsetName);
|
||||||
} else {// anonymous access
|
} else {// anonymous access
|
||||||
encodedAuthorization = null;
|
encodedAuthorization = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
users = new ConcurrentHashMap<String, GHUser>();
|
||||||
|
orgs = new ConcurrentHashMap<String, GHOrganization>();
|
||||||
this.rateLimitHandler = rateLimitHandler;
|
this.rateLimitHandler = rateLimitHandler;
|
||||||
|
this.abuseLimitHandler = abuseLimitHandler;
|
||||||
|
|
||||||
if (login==null && encodedAuthorization!=null)
|
if (login==null && encodedAuthorization!=null && jwtToken == null)
|
||||||
login = getMyself().getLogin();
|
login = getMyself().getLogin();
|
||||||
this.login = login;
|
this.login = login;
|
||||||
}
|
}
|
||||||
@@ -154,15 +167,33 @@ public class GitHub {
|
|||||||
/**
|
/**
|
||||||
* Version that connects to GitHub Enterprise.
|
* Version that connects to GitHub Enterprise.
|
||||||
*
|
*
|
||||||
* @param apiUrl
|
* @deprecated
|
||||||
* The URL of GitHub (or GitHub enterprise) API endpoint, such as "https://api.github.com" or
|
* Use {@link #connectToEnterpriseWithOAuth(String, String, String)}
|
||||||
* "http://ghe.acme.com/api/v3". Note that GitHub Enterprise has <tt>/api/v3</tt> in the URL.
|
|
||||||
* For historical reasons, this parameter still accepts the bare domain name, but that's considered deprecated.
|
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static GitHub connectToEnterprise(String apiUrl, String oauthAccessToken) throws IOException {
|
public static GitHub connectToEnterprise(String apiUrl, String oauthAccessToken) throws IOException {
|
||||||
return new GitHubBuilder().withEndpoint(apiUrl).withOAuthToken(oauthAccessToken).build();
|
return connectToEnterpriseWithOAuth(apiUrl,null,oauthAccessToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version that connects to GitHub Enterprise.
|
||||||
|
*
|
||||||
|
* @param apiUrl
|
||||||
|
* The URL of GitHub (or GitHub Enterprise) API endpoint, such as "https://api.github.com" or
|
||||||
|
* "http://ghe.acme.com/api/v3". Note that GitHub Enterprise has <code>/api/v3</code> in the URL.
|
||||||
|
* For historical reasons, this parameter still accepts the bare domain name, but that's considered deprecated.
|
||||||
|
*/
|
||||||
|
public static GitHub connectToEnterpriseWithOAuth(String apiUrl, String login, String oauthAccessToken) throws IOException {
|
||||||
|
return new GitHubBuilder().withEndpoint(apiUrl).withOAuthToken(oauthAccessToken, login).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version that connects to GitHub Enterprise.
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* Use with caution. Login with password is not a preferred method.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public static GitHub connectToEnterprise(String apiUrl, String login, String password) throws IOException {
|
public static GitHub connectToEnterprise(String apiUrl, String login, String password) throws IOException {
|
||||||
return new GitHubBuilder().withEndpoint(apiUrl).withPassword(login, password).build();
|
return new GitHubBuilder().withEndpoint(apiUrl).withPassword(login, password).build();
|
||||||
}
|
}
|
||||||
@@ -176,6 +207,7 @@ public class GitHub {
|
|||||||
* Either OAuth token or password is sufficient, so there's no point in passing both.
|
* Either OAuth token or password is sufficient, so there's no point in passing both.
|
||||||
* Use {@link #connectUsingPassword(String, String)} or {@link #connectUsingOAuth(String)}.
|
* Use {@link #connectUsingPassword(String, String)} or {@link #connectUsingOAuth(String)}.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static GitHub connect(String login, String oauthAccessToken, String password) throws IOException {
|
public static GitHub connect(String login, String oauthAccessToken, String password) throws IOException {
|
||||||
return new GitHubBuilder().withOAuthToken(oauthAccessToken, login).withPassword(login, password).build();
|
return new GitHubBuilder().withOAuthToken(oauthAccessToken, login).withPassword(login, password).build();
|
||||||
}
|
}
|
||||||
@@ -194,7 +226,7 @@ public class GitHub {
|
|||||||
/**
|
/**
|
||||||
* Connects to GitHub anonymously.
|
* Connects to GitHub anonymously.
|
||||||
*
|
*
|
||||||
* All operations that requires authentication will fail.
|
* All operations that require authentication will fail.
|
||||||
*/
|
*/
|
||||||
public static GitHub connectAnonymously() throws IOException {
|
public static GitHub connectAnonymously() throws IOException {
|
||||||
return new GitHubBuilder().build();
|
return new GitHubBuilder().build();
|
||||||
@@ -203,12 +235,30 @@ public class GitHub {
|
|||||||
/**
|
/**
|
||||||
* Connects to GitHub Enterprise anonymously.
|
* Connects to GitHub Enterprise anonymously.
|
||||||
*
|
*
|
||||||
* All operations that requires authentication will fail.
|
* All operations that require authentication will fail.
|
||||||
*/
|
*/
|
||||||
public static GitHub connectToEnterpriseAnonymously(String apiUrl) throws IOException {
|
public static GitHub connectToEnterpriseAnonymously(String apiUrl) throws IOException {
|
||||||
return new GitHubBuilder().withEndpoint(apiUrl).build();
|
return new GitHubBuilder().withEndpoint(apiUrl).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An offline-only {@link GitHub} useful for parsing event notification from an unknown source.
|
||||||
|
*
|
||||||
|
* All operations that require a connection will fail.
|
||||||
|
*
|
||||||
|
* @return An offline-only {@link GitHub}.
|
||||||
|
*/
|
||||||
|
public static GitHub offline() {
|
||||||
|
try {
|
||||||
|
return new GitHubBuilder()
|
||||||
|
.withEndpoint("https://api.github.invalid")
|
||||||
|
.withConnector(HttpConnector.OFFLINE)
|
||||||
|
.build();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException("The offline implementation constructor should not connect", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this an anonymous connection
|
* Is this an anonymous connection
|
||||||
* @return {@code true} if operations that require authentication will fail.
|
* @return {@code true} if operations that require authentication will fail.
|
||||||
@@ -217,10 +267,22 @@ public class GitHub {
|
|||||||
return login==null && encodedAuthorization==null;
|
return login==null && encodedAuthorization==null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this an always offline "connection".
|
||||||
|
* @return {@code true} if this is an always offline "connection".
|
||||||
|
*/
|
||||||
|
public boolean isOffline() {
|
||||||
|
return connector == HttpConnector.OFFLINE;
|
||||||
|
}
|
||||||
|
|
||||||
public HttpConnector getConnector() {
|
public HttpConnector getConnector() {
|
||||||
return connector;
|
return connector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getApiUrl() {
|
||||||
|
return apiUrl;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the custom connector used to make requests to GitHub.
|
* Sets the custom connector used to make requests to GitHub.
|
||||||
*/
|
*/
|
||||||
@@ -254,31 +316,78 @@ public class GitHub {
|
|||||||
*/
|
*/
|
||||||
public GHRateLimit getRateLimit() throws IOException {
|
public GHRateLimit getRateLimit() throws IOException {
|
||||||
try {
|
try {
|
||||||
return retrieve().to("/rate_limit", JsonRateLimit.class).rate;
|
return rateLimit = retrieve().to("/rate_limit", JsonRateLimit.class).rate;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
// GitHub Enterprise doesn't have the rate limit, so in that case
|
// GitHub Enterprise doesn't have the rate limit, so in that case
|
||||||
// return some big number that's not too big.
|
// return some big number that's not too big.
|
||||||
// see issue #78
|
// see issue #78
|
||||||
GHRateLimit r = new GHRateLimit();
|
GHRateLimit r = new GHRateLimit();
|
||||||
r.limit = r.remaining = 1000000;
|
r.limit = r.remaining = 1000000;
|
||||||
r.reset = new Date(System.currentTimeMillis() + TimeUnit.HOURS.toMillis(1));
|
long hour = 60L * 60L; // this is madness, storing the date as seconds in a Date object
|
||||||
return r;
|
r.reset = new Date(System.currentTimeMillis() / 1000L + hour);
|
||||||
|
return rateLimit = r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*package*/ void updateRateLimit(@Nonnull GHRateLimit observed) {
|
||||||
|
synchronized (headerRateLimitLock) {
|
||||||
|
if (headerRateLimit == null
|
||||||
|
|| headerRateLimit.getResetDate().getTime() < observed.getResetDate().getTime()
|
||||||
|
|| headerRateLimit.remaining > observed.remaining) {
|
||||||
|
headerRateLimit = observed;
|
||||||
|
LOGGER.log(FINE, "Rate limit now: {0}", headerRateLimit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the most recently observed rate limit data or {@code null} if either there is no rate limit
|
||||||
|
* (for example GitHub Enterprise) or if no requests have been made.
|
||||||
|
*
|
||||||
|
* @return the most recently observed rate limit data or {@code null}.
|
||||||
|
*/
|
||||||
|
@CheckForNull
|
||||||
|
public GHRateLimit lastRateLimit() {
|
||||||
|
synchronized (headerRateLimitLock) {
|
||||||
|
return headerRateLimit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current rate limit while trying not to actually make any remote requests unless absolutely necessary.
|
||||||
|
*
|
||||||
|
* @return the current rate limit data.
|
||||||
|
* @throws IOException if we couldn't get the current rate limit data.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
public GHRateLimit rateLimit() throws IOException {
|
||||||
|
synchronized (headerRateLimitLock) {
|
||||||
|
if (headerRateLimit != null) {
|
||||||
|
return headerRateLimit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GHRateLimit rateLimit = this.rateLimit;
|
||||||
|
if (rateLimit == null || rateLimit.getResetDate().getTime() < System.currentTimeMillis()) {
|
||||||
|
rateLimit = getRateLimit();
|
||||||
|
}
|
||||||
|
return rateLimit;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link GHUser} that represents yourself.
|
* Gets the {@link GHUser} that represents yourself.
|
||||||
*/
|
*/
|
||||||
@WithBridgeMethods(GHUser.class)
|
@WithBridgeMethods(GHUser.class)
|
||||||
public GHMyself getMyself() throws IOException {
|
public GHMyself getMyself() throws IOException {
|
||||||
requireCredential();
|
requireCredential();
|
||||||
|
synchronized (this) {
|
||||||
|
if (this.myself != null) return myself;
|
||||||
|
|
||||||
GHMyself u = retrieve().to("/user", GHMyself.class);
|
GHMyself u = retrieve().to("/user", GHMyself.class);
|
||||||
|
|
||||||
u.root = this;
|
u.root = this;
|
||||||
users.put(u.getLogin(), u);
|
this.myself = u;
|
||||||
|
return u;
|
||||||
return u;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -296,7 +405,7 @@ public class GitHub {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* clears all cached data in order for external changes (modifications and del
|
* clears all cached data in order for external changes (modifications and del) to be reflected
|
||||||
*/
|
*/
|
||||||
public void refreshCache() {
|
public void refreshCache() {
|
||||||
users.clear();
|
users.clear();
|
||||||
@@ -306,7 +415,7 @@ public class GitHub {
|
|||||||
/**
|
/**
|
||||||
* Interns the given {@link GHUser}.
|
* Interns the given {@link GHUser}.
|
||||||
*/
|
*/
|
||||||
protected GHUser getUser(GHUser orig) throws IOException {
|
protected GHUser getUser(GHUser orig) {
|
||||||
GHUser u = users.get(orig.getLogin());
|
GHUser u = users.get(orig.getLogin());
|
||||||
if (u==null) {
|
if (u==null) {
|
||||||
orig.root = this;
|
orig.root = this;
|
||||||
@@ -316,6 +425,9 @@ public class GitHub {
|
|||||||
return u;
|
return u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets {@link GHOrganization} specified by name.
|
||||||
|
*/
|
||||||
public GHOrganization getOrganization(String name) throws IOException {
|
public GHOrganization getOrganization(String name) throws IOException {
|
||||||
GHOrganization o = orgs.get(name);
|
GHOrganization o = orgs.get(name);
|
||||||
if (o==null) {
|
if (o==null) {
|
||||||
@@ -325,6 +437,27 @@ public class GitHub {
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of all organizations.
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHOrganization> listOrganizations() {
|
||||||
|
return listOrganizations(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of all organizations starting after the organization identifier specified by 'since'.
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/orgs/#parameters">List All Orgs - Parameters</a>
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHOrganization> listOrganizations(final String since) {
|
||||||
|
return retrieve()
|
||||||
|
.with("since",since)
|
||||||
|
.asPagedIterable(
|
||||||
|
"/organizations",
|
||||||
|
GHOrganization[].class,
|
||||||
|
item -> item.wrapUp(GitHub.this) );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the repository object from 'user/reponame' string that GitHub calls as "repository name"
|
* Gets the repository object from 'user/reponame' string that GitHub calls as "repository name"
|
||||||
*
|
*
|
||||||
@@ -336,7 +469,62 @@ public class GitHub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns a shallowly populated organizations.
|
* Gets the repository object from its ID
|
||||||
|
*/
|
||||||
|
public GHRepository getRepositoryById(String id) throws IOException {
|
||||||
|
return retrieve().to("/repositories/" + id, GHRepository.class).wrap(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of popular open source licenses
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/licenses/">GitHub API - Licenses</a>
|
||||||
|
*
|
||||||
|
* @return a list of popular open source licenses
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHLicense> listLicenses() throws IOException {
|
||||||
|
return retrieve()
|
||||||
|
.asPagedIterable(
|
||||||
|
"/licenses",
|
||||||
|
GHLicense[].class,
|
||||||
|
item -> item.wrap(GitHub.this) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all users.
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHUser> listUsers() throws IOException {
|
||||||
|
return retrieve()
|
||||||
|
.asPagedIterable(
|
||||||
|
"/users",
|
||||||
|
GHUser[].class,
|
||||||
|
item -> item.wrapUp(GitHub.this) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the full details for a license
|
||||||
|
*
|
||||||
|
* @param key The license key provided from the API
|
||||||
|
* @return The license details
|
||||||
|
* @see GHLicense#getKey()
|
||||||
|
*/
|
||||||
|
public GHLicense getLicense(String key) throws IOException {
|
||||||
|
return retrieve().to("/licenses/" + key, GHLicense.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets complete list of open invitations for current user.
|
||||||
|
*/
|
||||||
|
public List<GHInvitation> getMyInvitations() throws IOException {
|
||||||
|
GHInvitation[] invitations = retrieve().to("/user/repository_invitations", GHInvitation[].class);
|
||||||
|
for (GHInvitation i : invitations) {
|
||||||
|
i.wrapUp(this);
|
||||||
|
}
|
||||||
|
return Arrays.asList(invitations);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns shallowly populated organizations.
|
||||||
*
|
*
|
||||||
* To retrieve full organization details, you need to call {@link #getOrganization(String)}
|
* To retrieve full organization details, you need to call {@link #getOrganization(String)}
|
||||||
* TODO: make this automatic.
|
* TODO: make this automatic.
|
||||||
@@ -350,6 +538,32 @@ public class GitHub {
|
|||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias for {@link #getUserPublicOrganizations(String)}.
|
||||||
|
*/
|
||||||
|
public Map<String, GHOrganization> getUserPublicOrganizations(GHUser user) throws IOException {
|
||||||
|
return getUserPublicOrganizations( user.getLogin() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns a shallowly populated organizations.
|
||||||
|
*
|
||||||
|
* To retrieve full organization details, you need to call {@link #getOrganization(String)}
|
||||||
|
*
|
||||||
|
* @param login the user to retrieve public Organization membership information for
|
||||||
|
*
|
||||||
|
* @return the public Organization memberships for the user
|
||||||
|
*/
|
||||||
|
public Map<String, GHOrganization> getUserPublicOrganizations(String login) throws IOException {
|
||||||
|
GHOrganization[] orgs = retrieve().to("/users/" + login + "/orgs", GHOrganization[].class);
|
||||||
|
Map<String, GHOrganization> r = new HashMap<String, GHOrganization>();
|
||||||
|
for (GHOrganization o : orgs) {
|
||||||
|
// don't put 'o' into orgs because they are shallow
|
||||||
|
r.put(o.getLogin(),o.wrapUp(this));
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets complete map of organizations/teams that current user belongs to.
|
* Gets complete map of organizations/teams that current user belongs to.
|
||||||
@@ -373,6 +587,13 @@ public class GitHub {
|
|||||||
return allMyTeams;
|
return allMyTeams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a sigle team by ID.
|
||||||
|
*/
|
||||||
|
public GHTeam getTeam(int id) throws IOException {
|
||||||
|
return retrieve().to("/teams/" + id, GHTeam.class).wrapUp(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public events visible to you. Equivalent of what's displayed on https://github.com/
|
* Public events visible to you. Equivalent of what's displayed on https://github.com/
|
||||||
*/
|
*/
|
||||||
@@ -384,7 +605,7 @@ public class GitHub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a sigle gist by ID.
|
* Gets a single gist by ID.
|
||||||
*/
|
*/
|
||||||
public GHGist getGist(String id) throws IOException {
|
public GHGist getGist(String id) throws IOException {
|
||||||
return retrieve().to("/gists/"+id,GHGist.class).wrapUp(this);
|
return retrieve().to("/gists/"+id,GHGist.class).wrapUp(this);
|
||||||
@@ -415,6 +636,7 @@ public class GitHub {
|
|||||||
* @deprecated
|
* @deprecated
|
||||||
* Use {@link #createRepository(String)} that uses a builder pattern to let you control every aspect.
|
* Use {@link #createRepository(String)} that uses a builder pattern to let you control every aspect.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public GHRepository createRepository(String name, String description, String homepage, boolean isPublic) throws IOException {
|
public GHRepository createRepository(String name, String description, String homepage, boolean isPublic) throws IOException {
|
||||||
return createRepository(name).description(description).homepage(homepage).private_(!isPublic).create();
|
return createRepository(name).description(description).homepage(homepage).private_(!isPublic).create();
|
||||||
}
|
}
|
||||||
@@ -424,7 +646,7 @@ public class GitHub {
|
|||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* You use the returned builder to set various properties, then call {@link GHCreateRepositoryBuilder#create()}
|
* You use the returned builder to set various properties, then call {@link GHCreateRepositoryBuilder#create()}
|
||||||
* to finally createa repository.
|
* to finally create a repository.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* To create a repository in an organization, see
|
* To create a repository in an organization, see
|
||||||
@@ -450,18 +672,104 @@ public class GitHub {
|
|||||||
return requester.method("POST").to("/authorizations", GHAuthorization.class).wrap(this);
|
return requester.method("POST").to("/authorizations", GHAuthorization.class).wrap(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see <a href="https://developer.github.com/v3/oauth_authorizations/#get-or-create-an-authorization-for-a-specific-app">docs</a>
|
||||||
|
*/
|
||||||
|
public GHAuthorization createOrGetAuth(String clientId, String clientSecret, List<String> scopes, String note,
|
||||||
|
String note_url)
|
||||||
|
throws IOException {
|
||||||
|
Requester requester = new Requester(this)
|
||||||
|
.with("client_secret", clientSecret)
|
||||||
|
.with("scopes", scopes)
|
||||||
|
.with("note", note)
|
||||||
|
.with("note_url", note_url);
|
||||||
|
|
||||||
|
return requester.method("PUT").to("/authorizations/clients/" + clientId, GHAuthorization.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see <a href="https://developer.github.com/v3/oauth_authorizations/#delete-an-authorization">Delete an authorization</a>
|
||||||
|
*/
|
||||||
|
public void deleteAuth(long id) throws IOException {
|
||||||
|
retrieve().method("DELETE").to("/authorizations/" + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see <a href="https://developer.github.com/v3/oauth_authorizations/#check-an-authorization">Check an authorization</a>
|
||||||
|
*/
|
||||||
|
public GHAuthorization checkAuth(@Nonnull String clientId, @Nonnull String accessToken) throws IOException {
|
||||||
|
return retrieve().to("/applications/" + clientId + "/tokens/" + accessToken, GHAuthorization.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see <a href="https://developer.github.com/v3/oauth_authorizations/#reset-an-authorization">Reset an authorization</a>
|
||||||
|
*/
|
||||||
|
public GHAuthorization resetAuth(@Nonnull String clientId, @Nonnull String accessToken) throws IOException {
|
||||||
|
return retrieve().method("POST").to("/applications/" + clientId + "/tokens/" + accessToken, GHAuthorization.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of all authorizations.
|
||||||
|
* @see <a href="https://developer.github.com/v3/oauth_authorizations/#list-your-authorizations">List your authorizations</a>
|
||||||
|
*/
|
||||||
|
public PagedIterable<GHAuthorization> listMyAuthorizations() throws IOException {
|
||||||
|
return retrieve()
|
||||||
|
.asPagedIterable(
|
||||||
|
"/authorizations",
|
||||||
|
GHAuthorization[].class,
|
||||||
|
item -> item.wrap(GitHub.this) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the GitHub App associated with the authentication credentials used.
|
||||||
|
*
|
||||||
|
* You must use a JWT to access this endpoint.
|
||||||
|
*
|
||||||
|
* @see <a href="https://developer.github.com/v3/apps/#get-the-authenticated-github-app">Get the authenticated GitHub App</a>
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHApp getApp() throws IOException {
|
||||||
|
return retrieve().withPreview(MACHINE_MAN).to("/app", GHApp.class).wrapUp(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that the credential is valid.
|
* Ensures that the credential is valid.
|
||||||
*/
|
*/
|
||||||
public boolean isCredentialValid() throws IOException {
|
public boolean isCredentialValid() {
|
||||||
try {
|
try {
|
||||||
retrieve().to("/user", GHUser.class);
|
retrieve().to("/user", GHUser.class);
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
if (LOGGER.isLoggable(FINE))
|
||||||
|
LOGGER.log(FINE, "Exception validating credentials on " + this.apiUrl + " with login '" + this.login + "' " + e, e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*package*/ GHUser intern(GHUser user) throws IOException {
|
||||||
|
if (user==null) return user;
|
||||||
|
|
||||||
|
// if we already have this user in our map, use it
|
||||||
|
GHUser u = users.get(user.getLogin());
|
||||||
|
if (u!=null) return u;
|
||||||
|
|
||||||
|
// if not, remember this new user
|
||||||
|
users.putIfAbsent(user.getLogin(),user);
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProject getProject(long id) throws IOException {
|
||||||
|
return retrieve().withPreview(INERTIA).to("/projects/"+id, GHProject.class).wrap(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProjectColumn getProjectColumn(long id) throws IOException {
|
||||||
|
return retrieve().withPreview(INERTIA).to("/projects/columns/"+id, GHProjectColumn.class).wrap(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GHProjectCard getProjectCard(long id) throws IOException {
|
||||||
|
return retrieve().withPreview(INERTIA).to("/projects/columns/cards/"+id, GHProjectCard.class).wrap(this);
|
||||||
|
}
|
||||||
|
|
||||||
private static class GHApiInfo {
|
private static class GHApiInfo {
|
||||||
private String rate_limit_url;
|
private String rate_limit_url;
|
||||||
|
|
||||||
@@ -475,14 +783,77 @@ public class GitHub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensures that the API URL is valid.
|
* Tests the connection.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Verify that the API URL and credentials are valid to access this GitHub.
|
||||||
*
|
*
|
||||||
* <p>
|
* <p>
|
||||||
* This method returns normally if the endpoint is reachable and verified to be GitHub API URL.
|
* This method returns normally if the endpoint is reachable and verified to be GitHub API URL.
|
||||||
* Otherwise this method throws {@link IOException} to indicate the problem.
|
* Otherwise this method throws {@link IOException} to indicate the problem.
|
||||||
*/
|
*/
|
||||||
public void checkApiUrlValidity() throws IOException {
|
public void checkApiUrlValidity() throws IOException {
|
||||||
retrieve().to("/", GHApiInfo.class).check(apiUrl);
|
try {
|
||||||
|
retrieve().to("/", GHApiInfo.class).check(apiUrl);
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (isPrivateModeEnabled()) {
|
||||||
|
throw (IOException)new IOException("GitHub Enterprise server (" + apiUrl + ") with private mode enabled").initCause(e);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensures if a GitHub Enterprise server is configured in private mode.
|
||||||
|
*
|
||||||
|
* @return {@code true} if private mode is enabled. If it tries to use this method with GitHub, returns {@code
|
||||||
|
* false}.
|
||||||
|
*/
|
||||||
|
private boolean isPrivateModeEnabled() {
|
||||||
|
try {
|
||||||
|
HttpURLConnection uc = getConnector().connect(getApiURL("/"));
|
||||||
|
/*
|
||||||
|
$ curl -i https://github.mycompany.com/api/v3/
|
||||||
|
HTTP/1.1 401 Unauthorized
|
||||||
|
Server: GitHub.com
|
||||||
|
Date: Sat, 05 Mar 2016 19:45:01 GMT
|
||||||
|
Content-Type: application/json; charset=utf-8
|
||||||
|
Content-Length: 130
|
||||||
|
Status: 401 Unauthorized
|
||||||
|
X-GitHub-Media-Type: github.v3
|
||||||
|
X-XSS-Protection: 1; mode=block
|
||||||
|
X-Frame-Options: deny
|
||||||
|
Content-Security-Policy: default-src 'none'
|
||||||
|
Access-Control-Allow-Credentials: true
|
||||||
|
Access-Control-Expose-Headers: ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
|
||||||
|
Access-Control-Allow-Origin: *
|
||||||
|
X-GitHub-Request-Id: dbc70361-b11d-4131-9a7f-674b8edd0411
|
||||||
|
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
|
||||||
|
X-Content-Type-Options: nosniff
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
return uc.getResponseCode() == HTTP_UNAUTHORIZED
|
||||||
|
&& uc.getHeaderField("X-GitHub-Media-Type") != null;
|
||||||
|
} finally {
|
||||||
|
// ensure that the connection opened by getResponseCode gets closed
|
||||||
|
try {
|
||||||
|
IOUtils.closeQuietly(uc.getInputStream());
|
||||||
|
} catch (IOException ignore) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
IOUtils.closeQuietly(uc.getErrorStream());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search commits.
|
||||||
|
*/
|
||||||
|
@Preview @Deprecated
|
||||||
|
public GHCommitSearchBuilder searchCommits() {
|
||||||
|
return new GHCommitSearchBuilder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -532,21 +903,15 @@ public class GitHub {
|
|||||||
* This provides a dump of every public repository, in the order that they were created.
|
* This provides a dump of every public repository, in the order that they were created.
|
||||||
*
|
*
|
||||||
* @param since
|
* @param since
|
||||||
* The integer ID of the last Repository that you’ve seen. See {@link GHRepository#getId()}
|
* The numeric ID of the last Repository that you’ve seen. See {@link GHRepository#getId()}
|
||||||
* @see <a href="https://developer.github.com/v3/repos/#list-all-public-repositories">documentation</a>
|
* @see <a href="https://developer.github.com/v3/repos/#list-all-public-repositories">documentation</a>
|
||||||
*/
|
*/
|
||||||
public PagedIterable<GHRepository> listAllPublicRepositories(final String since) {
|
public PagedIterable<GHRepository> listAllPublicRepositories(final String since) {
|
||||||
return new PagedIterable<GHRepository>() {
|
return retrieve().with("since",since)
|
||||||
public PagedIterator<GHRepository> _iterator(int pageSize) {
|
.asPagedIterable(
|
||||||
return new PagedIterator<GHRepository>(retrieve().with("since",since).asIterator("/repositories", GHRepository[].class, pageSize)) {
|
"/repositories",
|
||||||
@Override
|
GHRepository[].class,
|
||||||
protected void wrapUp(GHRepository[] page) {
|
item -> item.wrap(GitHub.this) );
|
||||||
for (GHRepository c : page)
|
|
||||||
c.wrap(GitHub.this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -591,17 +956,26 @@ public class GitHub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ static String printDate(Date dt) {
|
/*package*/ static String printDate(Date dt) {
|
||||||
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").format(dt);
|
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||||
|
df.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||||
|
return df.format(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ static final ObjectMapper MAPPER = new ObjectMapper();
|
/*package*/ static final ObjectMapper MAPPER = new ObjectMapper();
|
||||||
|
|
||||||
private static final String[] TIME_FORMATS = {"yyyy/MM/dd HH:mm:ss ZZZZ","yyyy-MM-dd'T'HH:mm:ss'Z'"};
|
private static final String[] TIME_FORMATS = {
|
||||||
|
"yyyy/MM/dd HH:mm:ss ZZZZ",
|
||||||
|
"yyyy-MM-dd'T'HH:mm:ss'Z'",
|
||||||
|
"yyyy-MM-dd'T'HH:mm:ss.S'Z'" // GitHub App endpoints return a different date format
|
||||||
|
};
|
||||||
|
|
||||||
static {
|
static {
|
||||||
MAPPER.setVisibilityChecker(new Std(NONE, NONE, NONE, NONE, ANY));
|
MAPPER.setVisibilityChecker(new Std(NONE, NONE, NONE, NONE, ANY));
|
||||||
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||||
|
MAPPER.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* package */ static final String GITHUB_URL = "https://api.github.com";
|
/* package */ static final String GITHUB_URL = "https://api.github.com";
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(GitHub.class.getName());
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user