Commit ed4fbcf6b004bacfe9ad3c99296d543921c477ed

Authored by Alex Denisov
2 parents 38b17e4e 5cb9e7ee

Merge branch 'master' into fix_project_access_notification

Showing 953 changed files with 941 additions and 1039 deletions   Show diff stats
.gitignore
... ... @@ -22,4 +22,4 @@ config/unicorn.rb
22 22 db/data.yml
23 23 .idea
24 24 .DS_Store
25   -
  25 +.chef
... ...
.travis.yml
... ... @@ -9,6 +9,8 @@ branches:
9 9 - 'master'
10 10 rvm:
11 11 - 1.9.3
  12 +services:
  13 + - mysql
12 14 before_script:
13 15 - "cp config/database.yml.$DB config/database.yml"
14 16 - "cp config/gitlab.yml.example config/gitlab.yml"
... ...
Gemfile.lock
... ... @@ -323,7 +323,7 @@ GEM
323 323 multi_json (~> 1.0)
324 324 rubyzip
325 325 settingslogic (2.0.8)
326   - shoulda-matchers (1.1.0)
  326 + shoulda-matchers (1.3.0)
327 327 activesupport (>= 3.0.0)
328 328 simplecov (0.6.4)
329 329 multi_json (~> 1.0)
... ...
app/assets/images/emoji/+1.png 0 → 100755

5.01 KB

app/assets/images/emoji/-1.png 0 → 100755

4.95 KB

app/assets/images/emoji/100.png 0 → 100755

3.22 KB

app/assets/images/emoji/109.png 0 → 100755

3.61 KB

app/assets/images/emoji/1234.png 0 → 100755

4.64 KB

app/assets/images/emoji/8ball.png 0 → 100755

4.04 KB

app/assets/images/emoji/a.png 0 → 100755

3.08 KB

app/assets/images/emoji/ab.png 0 → 100755

3.77 KB

app/assets/images/emoji/abc.png 0 → 100755

4.15 KB

app/assets/images/emoji/abcd.png 0 → 100755

4.37 KB

app/assets/images/emoji/accept.png 0 → 100755

4.62 KB

app/assets/images/emoji/aerial_tramway.png 0 → 100755

3.41 KB

app/assets/images/emoji/airplane.png 0 → 100755

4.63 KB

app/assets/images/emoji/alarm_clock.png 0 → 100755

6.9 KB

app/assets/images/emoji/alien.png 0 → 100755

5.33 KB

app/assets/images/emoji/ambulance.png 0 → 100755

3.62 KB

app/assets/images/emoji/anchor.png 0 → 100755

4.37 KB

app/assets/images/emoji/angel.png 0 → 100755

6.52 KB

app/assets/images/emoji/anger.png 0 → 100755

3.01 KB

app/assets/images/emoji/angry.png 0 → 100755

4.92 KB

app/assets/images/emoji/ant.png 0 → 100755

2.78 KB

app/assets/images/emoji/apple.png 0 → 100755

5.5 KB

app/assets/images/emoji/aquarius.png 0 → 100755

4.98 KB

app/assets/images/emoji/aries.png 0 → 100755

4.24 KB

app/assets/images/emoji/arrow_backward.png 0 → 100755

3.11 KB

app/assets/images/emoji/arrow_double_down.png 0 → 100755

3.1 KB

app/assets/images/emoji/arrow_double_up.png 0 → 100755

3.53 KB

app/assets/images/emoji/arrow_down.png 0 → 100755

2.94 KB

app/assets/images/emoji/arrow_down_small.png 0 → 100755

2.87 KB

app/assets/images/emoji/arrow_forward.png 0 → 100755

3.13 KB

app/assets/images/emoji/arrow_heading_down.png 0 → 100755

3.44 KB

app/assets/images/emoji/arrow_heading_up.png 0 → 100755

3.44 KB

app/assets/images/emoji/arrow_left.png 0 → 100755

2.97 KB

app/assets/images/emoji/arrow_lower_left.png 0 → 100755

3.26 KB

app/assets/images/emoji/arrow_lower_right.png 0 → 100755

3.26 KB

app/assets/images/emoji/arrow_right.png 0 → 100755

2.95 KB

app/assets/images/emoji/arrow_right_hook.png 0 → 100755

3.63 KB

app/assets/images/emoji/arrow_up.png 0 → 100755

3 KB

app/assets/images/emoji/arrow_up_down.png 0 → 100755

3.46 KB

app/assets/images/emoji/arrow_up_small.png 0 → 100755

3.12 KB

app/assets/images/emoji/arrow_upper_left.png 0 → 100755

3.15 KB

app/assets/images/emoji/arrow_upper_right.png 0 → 100755

3.16 KB

app/assets/images/emoji/arrows_clockwise.png 0 → 100755

1.37 KB

app/assets/images/emoji/arrows_counterclockwise.png 0 → 100755

4.71 KB

app/assets/images/emoji/art.png 0 → 100755

6.59 KB

app/assets/images/emoji/articulated_lorry.png 0 → 100755

2.87 KB

app/assets/images/emoji/astonished.png 0 → 100755

5.9 KB

app/assets/images/emoji/atm.png 0 → 100755

3.98 KB

app/assets/images/emoji/b.png 0 → 100755

2.95 KB

app/assets/images/emoji/baby.png 0 → 100755

5.78 KB

app/assets/images/emoji/baby_bottle.png 0 → 100755

4.36 KB

app/assets/images/emoji/baby_chick.png 0 → 100755

3.87 KB

app/assets/images/emoji/baby_symbol.png 0 → 100755

2.9 KB

app/assets/images/emoji/baggage_claim.png 0 → 100755

3.42 KB

app/assets/images/emoji/balloon.png 0 → 100755

2.25 KB

app/assets/images/emoji/ballot_box_with_check.png 0 → 100755

1.79 KB

app/assets/images/emoji/bamboo.png 0 → 100755

4.56 KB

app/assets/images/emoji/banana.png 0 → 100755

3.82 KB

app/assets/images/emoji/bangbang.png 0 → 100755

1.35 KB

app/assets/images/emoji/bank.png 0 → 100755

5.45 KB

app/assets/images/emoji/bar_chart.png 0 → 100755

2.4 KB

app/assets/images/emoji/barber.png 0 → 100755

4.15 KB

app/assets/images/emoji/baseball.png 0 → 100755

5.89 KB

app/assets/images/emoji/basketball.png 0 → 100755

6.24 KB

app/assets/images/emoji/bath.png 0 → 100755

3.13 KB

app/assets/images/emoji/bathtub.png 0 → 100755

2.72 KB

app/assets/images/emoji/battery.png 0 → 100755

3.72 KB

app/assets/images/emoji/bear.png 0 → 100755

5.43 KB

app/assets/images/emoji/beer.png 0 → 100755

5.95 KB

app/assets/images/emoji/beers.png 0 → 100755

6.44 KB

app/assets/images/emoji/beetle.png 0 → 100755

5.13 KB

app/assets/images/emoji/beginner.png 0 → 100755

2.7 KB

app/assets/images/emoji/bell.png 0 → 100755

4.75 KB

app/assets/images/emoji/bento.png 0 → 100755

5.6 KB

app/assets/images/emoji/bicyclist.png 0 → 100755

6.33 KB

app/assets/images/emoji/bike.png 0 → 100755

4.61 KB

app/assets/images/emoji/bikini.png 0 → 100755

3.8 KB

app/assets/images/emoji/bird.png 0 → 100755

4.76 KB

app/assets/images/emoji/birthday.png 0 → 100755

5.28 KB

app/assets/images/emoji/black_circle.png 0 → 100755

2.31 KB

app/assets/images/emoji/black_joker.png 0 → 100755

3.79 KB

app/assets/images/emoji/black_nib.png 0 → 100755

2.3 KB

app/assets/images/emoji/black_square.png 0 → 100755

1.3 KB

app/assets/images/emoji/blossom.png 0 → 100755

4.13 KB

app/assets/images/emoji/blowfish.png 0 → 100755

3.66 KB

app/assets/images/emoji/blue_book.png 0 → 100755

4.97 KB

app/assets/images/emoji/blue_car.png 0 → 100755

3.99 KB

app/assets/images/emoji/blue_heart.png 0 → 100755

4 KB

app/assets/images/emoji/blush.png 0 → 100755

5.07 KB

app/assets/images/emoji/boar.png 0 → 100755

4.73 KB

app/assets/images/emoji/boat.png 0 → 100755

3.74 KB

app/assets/images/emoji/bomb.png 0 → 100755

5.09 KB

app/assets/images/emoji/book.png 0 → 100755

5.91 KB

app/assets/images/emoji/bookmark.png 0 → 100755

4.59 KB

app/assets/images/emoji/bookmark_tabs.png 0 → 100755

3.09 KB

app/assets/images/emoji/books.png 0 → 100755

6.39 KB

app/assets/images/emoji/boot.png 0 → 100755

3.25 KB

app/assets/images/emoji/bouquet.png 0 → 100755

6.75 KB

app/assets/images/emoji/bow.png 0 → 100755

5.02 KB

app/assets/images/emoji/bowling.png 0 → 100755

4.09 KB

app/assets/images/emoji/bowtie.png 0 → 100755

6.33 KB

app/assets/images/emoji/boy.png 0 → 100755

5.81 KB

app/assets/images/emoji/bread.png 0 → 100755

6.07 KB

app/assets/images/emoji/bride_with_veil.png 0 → 100755

8.32 KB

app/assets/images/emoji/bridge_at_night.png 0 → 100755

5.02 KB

app/assets/images/emoji/briefcase.png 0 → 100755

2.63 KB

app/assets/images/emoji/broken_heart.png 0 → 100755

4.02 KB

app/assets/images/emoji/bug.png 0 → 100755

5.81 KB

app/assets/images/emoji/bulb.png 0 → 100755

4.38 KB

app/assets/images/emoji/bullettrain_front.png 0 → 100755

4.88 KB

app/assets/images/emoji/bullettrain_side.png 0 → 100755

3.75 KB

app/assets/images/emoji/bus.png 0 → 100755

3.97 KB

app/assets/images/emoji/busstop.png 0 → 100755

1.64 KB

app/assets/images/emoji/bust_in_silhouette.png 0 → 100755

1.96 KB

app/assets/images/emoji/busts_in_silhouette.png 0 → 100755

2.95 KB

app/assets/images/emoji/cactus.png 0 → 100755

4.4 KB

app/assets/images/emoji/cake.png 0 → 100755

5.99 KB

app/assets/images/emoji/calendar.png 0 → 100755

2.85 KB

app/assets/images/emoji/calling.png 0 → 100755

3.94 KB

app/assets/images/emoji/camel.png 0 → 100755

4.38 KB

app/assets/images/emoji/camera.png 0 → 100755

4.55 KB

app/assets/images/emoji/cancer.png 0 → 100755

5.26 KB

app/assets/images/emoji/candy.png 0 → 100755

4.4 KB

app/assets/images/emoji/capital_abcd.png 0 → 100755

5.02 KB

app/assets/images/emoji/capricorn.png 0 → 100755

4.56 KB

app/assets/images/emoji/car.png 0 → 100755

4.18 KB

app/assets/images/emoji/card_index.png 0 → 100755

3.66 KB

app/assets/images/emoji/carousel_horse.png 0 → 100755

5.75 KB

app/assets/images/emoji/cat.png 0 → 100755

5.85 KB

app/assets/images/emoji/cat2.png 0 → 100755

5.59 KB

app/assets/images/emoji/cd.png 0 → 100755

6.56 KB

app/assets/images/emoji/chart.png 0 → 100755

4.23 KB

app/assets/images/emoji/chart_with_downwards_trend.png 0 → 100755

2.84 KB

app/assets/images/emoji/chart_with_upwards_trend.png 0 → 100755

2.87 KB

app/assets/images/emoji/checkered_flag.png 0 → 100755

1.64 KB

app/assets/images/emoji/cherries.png 0 → 100755

5.47 KB

app/assets/images/emoji/cherry_blossom.png 0 → 100755

7.01 KB

app/assets/images/emoji/chestnut.png 0 → 100755

5.74 KB

app/assets/images/emoji/chicken.png 0 → 100755

3.89 KB

app/assets/images/emoji/children_crossing.png 0 → 100755

3.38 KB

app/assets/images/emoji/chocolate_bar.png 0 → 100755

5.13 KB

app/assets/images/emoji/christmas_tree.png 0 → 100755

4.61 KB

app/assets/images/emoji/church.png 0 → 100755

4.54 KB

app/assets/images/emoji/cinema.png 0 → 100755

3.49 KB

app/assets/images/emoji/circus_tent.png 0 → 100755

4.57 KB

app/assets/images/emoji/city_sunrise.png 0 → 100755

4.21 KB

app/assets/images/emoji/city_sunset.png 0 → 100755

3.75 KB

app/assets/images/emoji/cl.png 0 → 100755

3.41 KB

app/assets/images/emoji/clap.png 0 → 100755

6.94 KB

app/assets/images/emoji/clapper.png 0 → 100755

4.09 KB

app/assets/images/emoji/clipboard.png 0 → 100755

4.55 KB

app/assets/images/emoji/clock1.png 0 → 100755

2.53 KB

app/assets/images/emoji/clock10.png 0 → 100755

2.53 KB

app/assets/images/emoji/clock1030.png 0 → 100755

2.8 KB

app/assets/images/emoji/clock11.png 0 → 100755

2.53 KB

app/assets/images/emoji/clock1130.png 0 → 100755

2.79 KB

app/assets/images/emoji/clock12.png 0 → 100755

2.45 KB

app/assets/images/emoji/clock1230.png 0 → 100755

2.73 KB

app/assets/images/emoji/clock130.png 0 → 100755

2.78 KB

app/assets/images/emoji/clock2.png 0 → 100755

2.53 KB

app/assets/images/emoji/clock230.png 0 → 100755

2.79 KB

app/assets/images/emoji/clock3.png 0 → 100755

2.43 KB

app/assets/images/emoji/clock330.png 0 → 100755

2.67 KB

app/assets/images/emoji/clock4.png 0 → 100755

2.56 KB

app/assets/images/emoji/clock430.png 0 → 100755

2.78 KB

app/assets/images/emoji/clock5.png 0 → 100755

2.56 KB

app/assets/images/emoji/clock530.png 0 → 100755

2.77 KB

app/assets/images/emoji/clock6.png 0 → 100755

2.52 KB

app/assets/images/emoji/clock630.png 0 → 100755

2.67 KB

app/assets/images/emoji/clock7.png 0 → 100755

2.55 KB

app/assets/images/emoji/clock730.png 0 → 100755

2.75 KB

app/assets/images/emoji/clock8.png 0 → 100755

2.54 KB

app/assets/images/emoji/clock830.png 0 → 100755

2.78 KB

app/assets/images/emoji/clock9.png 0 → 100755

2.43 KB

app/assets/images/emoji/clock930.png 0 → 100755

2.68 KB

app/assets/images/emoji/closed_book.png 0 → 100755

4.73 KB

app/assets/images/emoji/closed_lock_with_key.png 0 → 100755

5.57 KB

app/assets/images/emoji/closed_umbrella.png 0 → 100755

3.78 KB

app/assets/images/emoji/cloud.png 0 → 100755

3.77 KB

app/assets/images/emoji/clubs.png 0 → 100755

1.65 KB

app/assets/images/emoji/cn.png 0 → 100755

3.55 KB

app/assets/images/emoji/cocktail.png 0 → 100755

2.88 KB

app/assets/images/emoji/coffee.png 0 → 100755

4.21 KB

app/assets/images/emoji/cold_sweat.png 0 → 100755

5.83 KB

app/assets/images/emoji/collision.png 0 → 100755

3.69 KB

app/assets/images/emoji/computer.png 0 → 100755

1.67 KB

app/assets/images/emoji/confetti_ball.png 0 → 100755

5.39 KB

app/assets/images/emoji/confounded.png 0 → 100755

5.72 KB

app/assets/images/emoji/congratulations.png 0 → 100755

4.77 KB

app/assets/images/emoji/construction.png 0 → 100755

3.61 KB

app/assets/images/emoji/construction_worker.png 0 → 100755

6.05 KB

app/assets/images/emoji/convenience_store.png 0 → 100755

3.98 KB

app/assets/images/emoji/cookie.png 0 → 100755

7.96 KB

app/assets/images/emoji/cool.png 0 → 100755

4.08 KB

app/assets/images/emoji/cop.png 0 → 100755

6.97 KB

app/assets/images/emoji/copyright.png 0 → 100755

1.54 KB

app/assets/images/emoji/corn.png 0 → 100755

6.54 KB

app/assets/images/emoji/couple.png 0 → 100755

7.44 KB

app/assets/images/emoji/couple_with_heart.png 0 → 100755

7.2 KB

app/assets/images/emoji/couplekiss.png 0 → 100755

7.05 KB

app/assets/images/emoji/cow.png 0 → 100755

5.61 KB

app/assets/images/emoji/cow2.png 0 → 100755

5.18 KB

app/assets/images/emoji/credit_card.png 0 → 100755

2.59 KB

app/assets/images/emoji/crocodile.png 0 → 100755

5.98 KB

app/assets/images/emoji/crossed_flags.png 0 → 100755

3.92 KB

app/assets/images/emoji/crown.png 0 → 100755

5.52 KB

app/assets/images/emoji/cry.png 0 → 100755

5.57 KB

app/assets/images/emoji/crying_cat_face.png 0 → 100755

6.53 KB

app/assets/images/emoji/crystal_ball.png 0 → 100755

6.09 KB

app/assets/images/emoji/cupid.png 0 → 100755

5.29 KB

app/assets/images/emoji/curly_loop.png 0 → 100755

1.23 KB

app/assets/images/emoji/currency_exchange.png 0 → 100755

1.91 KB

app/assets/images/emoji/curry.png 0 → 100755

5.21 KB

app/assets/images/emoji/custard.png 0 → 100755

5.67 KB

app/assets/images/emoji/customs.png 0 → 100755

3.81 KB

app/assets/images/emoji/cyclone.png 0 → 100755

4.78 KB

app/assets/images/emoji/dancer.png 0 → 100755

3.65 KB

app/assets/images/emoji/dancers.png 0 → 100755

7.73 KB

app/assets/images/emoji/dango.png 0 → 100755

4.34 KB

app/assets/images/emoji/dart.png 0 → 100755

5.33 KB

app/assets/images/emoji/dash.png 0 → 100755

5.32 KB

app/assets/images/emoji/date.png 0 → 100755

2.91 KB

app/assets/images/emoji/de.png 0 → 100755

2.58 KB

app/assets/images/emoji/deciduous_tree.png 0 → 100755

7.2 KB

app/assets/images/emoji/department_store.png 0 → 100755

5.04 KB

app/assets/images/emoji/diamond_shape_with_a_dot_inside.png 0 → 100755

5.56 KB

app/assets/images/emoji/diamonds.png 0 → 100755

2.72 KB

app/assets/images/emoji/disappointed.png 0 → 100755

4.65 KB

app/assets/images/emoji/dizzy.png 0 → 100755

2.97 KB

app/assets/images/emoji/dizzy_face.png 0 → 100755

6.13 KB

app/assets/images/emoji/do_not_litter.png 0 → 100755

5.15 KB

app/assets/images/emoji/dog.png 0 → 100755

5.81 KB

app/assets/images/emoji/dog2.png 0 → 100755

5.79 KB

app/assets/images/emoji/dollar.png 0 → 100755

4.51 KB

app/assets/images/emoji/dolls.png 0 → 100755

6.97 KB

app/assets/images/emoji/dolphin.png 0 → 100755

4.24 KB

app/assets/images/emoji/door.png 0 → 100755

3.23 KB

app/assets/images/emoji/doughnut.png 0 → 100755

5.09 KB

app/assets/images/emoji/dragon.png 0 → 100755

7.64 KB

app/assets/images/emoji/dragon_face.png 0 → 100755

6.58 KB

app/assets/images/emoji/dress.png 0 → 100755

3.55 KB

app/assets/images/emoji/dromedary_camel.png 0 → 100755

5.02 KB

app/assets/images/emoji/droplet.png 0 → 100755

3.2 KB

app/assets/images/emoji/dvd.png 0 → 100755

6.83 KB

app/assets/images/emoji/e-mail.png 0 → 100755

2.08 KB

app/assets/images/emoji/ear.png 0 → 100755

4.23 KB

app/assets/images/emoji/ear_of_rice.png 0 → 100755

4.65 KB

app/assets/images/emoji/earth_africa.png 0 → 100755

7 KB

app/assets/images/emoji/earth_americas.png 0 → 100755

6.87 KB

app/assets/images/emoji/earth_asia.png 0 → 100755

7.13 KB

app/assets/images/emoji/egg.png 0 → 100755

5.09 KB

app/assets/images/emoji/eggplant.png 0 → 100755

4.56 KB

app/assets/images/emoji/eight.png 0 → 100755

3.75 KB

app/assets/images/emoji/eight_pointed_black_star.png 0 → 100755

3.21 KB

app/assets/images/emoji/eight_spoked_asterisk.png 0 → 100755

3.92 KB

app/assets/images/emoji/electric_plug.png 0 → 100755

2.75 KB

app/assets/images/emoji/elephant.png 0 → 100755

4.97 KB

app/assets/images/emoji/email.png 0 → 100755

2.63 KB

app/assets/images/emoji/end.png 0 → 100755

1.44 KB

app/assets/images/emoji/envelope.png 0 → 100755

1.62 KB

app/assets/images/emoji/es.png 0 → 100755

4.2 KB

app/assets/images/emoji/euro.png 0 → 100755

3.85 KB

app/assets/images/emoji/european_castle.png 0 → 100755

5.3 KB

app/assets/images/emoji/european_post_office.png 0 → 100755

4.7 KB

app/assets/images/emoji/evergreen_tree.png 0 → 100755

4.81 KB

app/assets/images/emoji/exclamation.png 0 → 100755

1.15 KB

app/assets/images/emoji/eyeglasses.png 0 → 100755

4.81 KB

app/assets/images/emoji/eyes.png 0 → 100755

4.29 KB

app/assets/images/emoji/facepunch.png 0 → 100755

4.76 KB

app/assets/images/emoji/factory.png 0 → 100755

5.43 KB

app/assets/images/emoji/fallen_leaf.png 0 → 100755

4.78 KB

app/assets/images/emoji/family.png 0 → 100755

7.04 KB

app/assets/images/emoji/fast_forward.png 0 → 100755

3.03 KB

app/assets/images/emoji/fax.png 0 → 100755

4.54 KB

app/assets/images/emoji/fearful.png 0 → 100755

5.47 KB

app/assets/images/emoji/feelsgood.png 0 → 100755

1.12 KB

app/assets/images/emoji/feet.png 0 → 100755

1.49 KB

app/assets/images/emoji/ferris_wheel.png 0 → 100755

6.07 KB

app/assets/images/emoji/file_folder.png 0 → 100755

3.92 KB

app/assets/images/emoji/finnadie.png 0 → 100755

1.16 KB

app/assets/images/emoji/fire.png 0 → 100755

3.79 KB

app/assets/images/emoji/fire_engine.png 0 → 100755

4.75 KB

app/assets/images/emoji/fireworks.png 0 → 100755

6.12 KB

app/assets/images/emoji/first_quarter_moon.png 0 → 100755

5.83 KB

app/assets/images/emoji/first_quarter_moon_with_face.png 0 → 100755

4.18 KB

app/assets/images/emoji/fish.png 0 → 100755

4.61 KB

app/assets/images/emoji/fish_cake.png 0 → 100755

5.68 KB

app/assets/images/emoji/fishing_pole_and_fish.png 0 → 100755

4.37 KB

app/assets/images/emoji/fist.png 0 → 100755

5.74 KB

app/assets/images/emoji/five.png 0 → 100755

3.51 KB

app/assets/images/emoji/flags.png 0 → 100755

5.98 KB

app/assets/images/emoji/flashlight.png 0 → 100755

4.91 KB

app/assets/images/emoji/floppy_disk.png 0 → 100755

3.14 KB

app/assets/images/emoji/flower_playing_cards.png 0 → 100755

3.35 KB

app/assets/images/emoji/flushed.png 0 → 100755

5.71 KB

app/assets/images/emoji/foggy.png 0 → 100755

4.51 KB

app/assets/images/emoji/football.png 0 → 100755

6.55 KB

app/assets/images/emoji/fork_and_knife.png 0 → 100755

3.52 KB

app/assets/images/emoji/fountain.png 0 → 100755

4.97 KB

app/assets/images/emoji/four.png 0 → 100755

3.1 KB

app/assets/images/emoji/four_leaf_clover.png 0 → 100755

5.85 KB

app/assets/images/emoji/fr.png 0 → 100755

3.32 KB

app/assets/images/emoji/free.png 0 → 100755

3.52 KB

app/assets/images/emoji/fried_shrimp.png 0 → 100755

7.37 KB

app/assets/images/emoji/fries.png 0 → 100755

6.25 KB

app/assets/images/emoji/frog.png 0 → 100755

4.71 KB

app/assets/images/emoji/fuelpump.png 0 → 100755

4.2 KB

app/assets/images/emoji/full_moon.png 0 → 100755

6.31 KB

app/assets/images/emoji/full_moon_with_face.png 0 → 100755

7.05 KB

app/assets/images/emoji/game_die.png 0 → 100755

2.89 KB

app/assets/images/emoji/gb.png 0 → 100755

5.76 KB

app/assets/images/emoji/gem.png 0 → 100755

4.74 KB

app/assets/images/emoji/gemini.png 0 → 100755

4.2 KB

app/assets/images/emoji/ghost.png 0 → 100755

4.41 KB

app/assets/images/emoji/gift.png 0 → 100755

6.55 KB

app/assets/images/emoji/gift_heart.png 0 → 100755

5.87 KB

app/assets/images/emoji/girl.png 0 → 100755

6.17 KB

app/assets/images/emoji/globe_with_meridians.png 0 → 100755

5.7 KB

app/assets/images/emoji/goat.png 0 → 100755

4.77 KB

app/assets/images/emoji/goberserk.png 0 → 100755

1.3 KB

app/assets/images/emoji/godmode.png 0 → 100755

1.02 KB

app/assets/images/emoji/golf.png 0 → 100755

3.46 KB

app/assets/images/emoji/grapes.png 0 → 100755

5.3 KB

app/assets/images/emoji/green_apple.png 0 → 100755

6.06 KB

app/assets/images/emoji/green_book.png 0 → 100755

4.97 KB

app/assets/images/emoji/green_heart.png 0 → 100755

4.33 KB

app/assets/images/emoji/grey_exclamation.png 0 → 100755

1.12 KB

app/assets/images/emoji/grey_question.png 0 → 100755

1.03 KB

app/assets/images/emoji/grin.png 0 → 100755

5.59 KB

app/assets/images/emoji/guardsman.png 0 → 100755

3.5 KB

app/assets/images/emoji/guitar.png 0 → 100755

4.28 KB

app/assets/images/emoji/gun.png 0 → 100755

3.09 KB

app/assets/images/emoji/haircut.png 0 → 100755

6.93 KB

app/assets/images/emoji/hamburger.png 0 → 100755

5.57 KB

app/assets/images/emoji/hammer.png 0 → 100755

3.58 KB

app/assets/images/emoji/hamster.png 0 → 100755

7.05 KB

app/assets/images/emoji/hand.png 0 → 100755

4.06 KB

app/assets/images/emoji/handbag.png 0 → 100755

5.32 KB

app/assets/images/emoji/hankey.png 0 → 100755

4.64 KB

app/assets/images/emoji/hash.png 0 → 100755

3.65 KB

app/assets/images/emoji/hatched_chick.png 0 → 100755

5.51 KB

app/assets/images/emoji/hatching_chick.png 0 → 100755

5.79 KB

app/assets/images/emoji/headphones.png 0 → 100755

1.87 KB

app/assets/images/emoji/hear_no_evil.png 0 → 100755

6.4 KB

app/assets/images/emoji/heart.png 0 → 100755

3.22 KB

app/assets/images/emoji/heart_decoration.png 0 → 100755

3.42 KB

app/assets/images/emoji/heart_eyes.png 0 → 100755

5.62 KB

app/assets/images/emoji/heart_eyes_cat.png 0 → 100755

6.03 KB

app/assets/images/emoji/heartbeat.png 0 → 100755

3.96 KB

app/assets/images/emoji/heartpulse.png 0 → 100755

6.12 KB

app/assets/images/emoji/hearts.png 0 → 100755

2.86 KB

app/assets/images/emoji/heavy_check_mark.png 0 → 100755

1.08 KB

app/assets/images/emoji/heavy_division_sign.png 0 → 100755

340 Bytes

app/assets/images/emoji/heavy_dollar_sign.png 0 → 100755

1.38 KB

app/assets/images/emoji/heavy_exclamation_mark.png 0 → 100755

1.28 KB

app/assets/images/emoji/heavy_minus_sign.png 0 → 100755

197 Bytes

app/assets/images/emoji/heavy_multiplication_x.png 0 → 100755

591 Bytes

app/assets/images/emoji/heavy_plus_sign.png 0 → 100755

315 Bytes

app/assets/images/emoji/helicopter.png 0 → 100755

4 KB

app/assets/images/emoji/herb.png 0 → 100755

5.75 KB

app/assets/images/emoji/hibiscus.png 0 → 100755

8.13 KB

app/assets/images/emoji/high_brightness.png 0 → 100755

3.96 KB

app/assets/images/emoji/high_heel.png 0 → 100755

4.45 KB

app/assets/images/emoji/hocho.png 0 → 100755

2.45 KB

app/assets/images/emoji/honey_pot.png 0 → 100755

5.69 KB

app/assets/images/emoji/honeybee.png 0 → 100755

5.71 KB

app/assets/images/emoji/horse.png 0 → 100755

4.47 KB

app/assets/images/emoji/horse_racing.png 0 → 100755

5.77 KB

app/assets/images/emoji/hospital.png 0 → 100755

4.77 KB

app/assets/images/emoji/hotel.png 0 → 100755

5 KB

app/assets/images/emoji/hotsprings.png 0 → 100755

3.46 KB

app/assets/images/emoji/hourglass.png 0 → 100755

4.39 KB

app/assets/images/emoji/house.png 0 → 100755

3.43 KB

app/assets/images/emoji/hurtrealbad.png 0 → 100755

1.42 KB

app/assets/images/emoji/ice_cream.png 0 → 100755

5.34 KB

app/assets/images/emoji/icecream.png 0 → 100755

4.5 KB

app/assets/images/emoji/id.png 0 → 100755

3.81 KB

app/assets/images/emoji/ideograph_advantage.png 0 → 100755

3.02 KB

app/assets/images/emoji/imp.png 0 → 100755

6.48 KB

app/assets/images/emoji/inbox_tray.png 0 → 100755

3.61 KB

app/assets/images/emoji/incoming_envelope.png 0 → 100755

2.15 KB

app/assets/images/emoji/information_desk_person.png 0 → 100755

6.45 KB

app/assets/images/emoji/information_source.png 0 → 100755

3.58 KB

app/assets/images/emoji/innocent.png 0 → 100755

6.84 KB

app/assets/images/emoji/interrobang.png 0 → 100755

2.81 KB

app/assets/images/emoji/iphone.png 0 → 100755

3.42 KB

app/assets/images/emoji/it.png 0 → 100755

3.41 KB

app/assets/images/emoji/izakaya_lantern.png 0 → 100755

3.97 KB

app/assets/images/emoji/jack_o_lantern.png 0 → 100755

5.5 KB

app/assets/images/emoji/japan.png 0 → 100755

3.99 KB

app/assets/images/emoji/japanese_castle.png 0 → 100755

4.82 KB

app/assets/images/emoji/japanese_goblin.png 0 → 100755

5.04 KB

app/assets/images/emoji/japanese_ogre.png 0 → 100755

6.98 KB

app/assets/images/emoji/jeans.png 0 → 100755

3.39 KB

app/assets/images/emoji/joy.png 0 → 100755

6.19 KB

app/assets/images/emoji/joy_cat.png 0 → 100755

7.02 KB

app/assets/images/emoji/jp.png 0 → 100755

2.76 KB

app/assets/images/emoji/key.png 0 → 100755

3.37 KB

app/assets/images/emoji/keycap_ten.png 0 → 100755

4 KB

app/assets/images/emoji/kimono.png 0 → 100755

4.82 KB

app/assets/images/emoji/kiss.png 0 → 100755

6.13 KB

app/assets/images/emoji/kissing_cat.png 0 → 100755

6.64 KB

app/assets/images/emoji/kissing_face.png 0 → 100755

5.43 KB

app/assets/images/emoji/kissing_heart.png 0 → 100755

5.63 KB

app/assets/images/emoji/koala.png 0 → 100755

5.55 KB

app/assets/images/emoji/koko.png 0 → 100755

2.79 KB

app/assets/images/emoji/kr.png 0 → 100755

4.99 KB

app/assets/images/emoji/large_blue_circle.png 0 → 100755

4.53 KB

app/assets/images/emoji/large_blue_diamond.png 0 → 100755

3.7 KB

app/assets/images/emoji/large_orange_diamond.png 0 → 100755

3.81 KB

app/assets/images/emoji/last_quarter_moon.png 0 → 100755

6.03 KB

app/assets/images/emoji/last_quarter_moon_with_face.png 0 → 100755

4.23 KB

app/assets/images/emoji/laughing.png 0 → 100755

6.2 KB

app/assets/images/emoji/leaves.png 0 → 100755

5.44 KB

app/assets/images/emoji/ledger.png 0 → 100755

5.78 KB

app/assets/images/emoji/left_luggage.png 0 → 100755

3.93 KB

app/assets/images/emoji/left_right_arrow.png 0 → 100755

3.33 KB

app/assets/images/emoji/leftwards_arrow_with_hook.png 0 → 100755

3.69 KB

app/assets/images/emoji/lemon.png 0 → 100755

5.91 KB

app/assets/images/emoji/leo.png 0 → 100755

4.8 KB

app/assets/images/emoji/leopard.png 0 → 100755

5.26 KB

app/assets/images/emoji/libra.png 0 → 100755

4.13 KB

app/assets/images/emoji/light_rail.png 0 → 100755

3.7 KB

app/assets/images/emoji/link.png 0 → 100755

2.59 KB

app/assets/images/emoji/lips.png 0 → 100755

3.65 KB

app/assets/images/emoji/lipstick.png 0 → 100755

3.3 KB

app/assets/images/emoji/lock.png 0 → 100755

3.59 KB

app/assets/images/emoji/lock_with_ink_pen.png 0 → 100755

4.85 KB

app/assets/images/emoji/lollipop.png 0 → 100755

5.64 KB

app/assets/images/emoji/loop.png 0 → 100755

3.34 KB

app/assets/images/emoji/loudspeaker.png 0 → 100755

5.86 KB

app/assets/images/emoji/love_hotel.png 0 → 100755

5.8 KB

app/assets/images/emoji/love_letter.png 0 → 100755

2.41 KB

app/assets/images/emoji/low_brightness.png 0 → 100755

2.44 KB

app/assets/images/emoji/m.png 0 → 100755

4.63 KB

app/assets/images/emoji/mag.png 0 → 100755

2.97 KB

app/assets/images/emoji/mag_right.png 0 → 100755

3.54 KB

app/assets/images/emoji/mahjong.png 0 → 100755

3.23 KB

app/assets/images/emoji/mailbox.png 0 → 100755

4.1 KB

app/assets/images/emoji/mailbox_closed.png 0 → 100755

4.26 KB

app/assets/images/emoji/mailbox_with_mail.png 0 → 100755

4.47 KB

app/assets/images/emoji/mailbox_with_no_mail.png 0 → 100755

3.03 KB

app/assets/images/emoji/man.png 0 → 100755

5.88 KB

app/assets/images/emoji/man_with_gua_pi_mao.png 0 → 100755

5.2 KB

app/assets/images/emoji/man_with_turban.png 0 → 100755

6.38 KB

app/assets/images/emoji/mans_shoe.png 0 → 100755

4.64 KB

app/assets/images/emoji/maple_leaf.png 0 → 100755

4.35 KB

app/assets/images/emoji/mask.png 0 → 100755

5.11 KB

app/assets/images/emoji/massage.png 0 → 100755

5.89 KB

app/assets/images/emoji/meat_on_bone.png 0 → 100755

5.4 KB

app/assets/images/emoji/mega.png 0 → 100755

4.57 KB

app/assets/images/emoji/melon.png 0 → 100755

8.04 KB

app/assets/images/emoji/memo.png 0 → 100755

4.83 KB

app/assets/images/emoji/mens.png 0 → 100755

3.29 KB

app/assets/images/emoji/metal.png 0 → 100755

3.03 KB

app/assets/images/emoji/metro.png 0 → 100755

3.32 KB

app/assets/images/emoji/microphone.png 0 → 100755

3.59 KB

app/assets/images/emoji/microscope.png 0 → 100755

4.04 KB

app/assets/images/emoji/milky_way.png 0 → 100755

5.74 KB

app/assets/images/emoji/minibus.png 0 → 100755

3.04 KB

app/assets/images/emoji/minidisc.png 0 → 100755

5.46 KB

app/assets/images/emoji/mobile_phone_off.png 0 → 100755

3.44 KB

app/assets/images/emoji/money_with_wings.png 0 → 100755

7.41 KB

app/assets/images/emoji/moneybag.png 0 → 100755

5.37 KB

app/assets/images/emoji/monkey.png 0 → 100755

4.86 KB

app/assets/images/emoji/monkey_face.png 0 → 100755

5.22 KB

app/assets/images/emoji/monorail.png 0 → 100755

4.21 KB

app/assets/images/emoji/moon.png 0 → 100755

3.46 KB

app/assets/images/emoji/mortar_board.png 0 → 100755

4.07 KB

app/assets/images/emoji/mount_fuji.png 0 → 100755

4.89 KB

app/assets/images/emoji/mountain_bicyclist.png 0 → 100755

9.29 KB

app/assets/images/emoji/mountain_cableway.png 0 → 100755

4.3 KB

app/assets/images/emoji/mountain_railway.png 0 → 100755

7.27 KB

app/assets/images/emoji/mouse.png 0 → 100755

6.47 KB

app/assets/images/emoji/mouse2.png 0 → 100755

3.99 KB

app/assets/images/emoji/movie_camera.png 0 → 100755

3.99 KB

app/assets/images/emoji/moyai.png 0 → 100755

2.12 KB

app/assets/images/emoji/muscle.png 0 → 100755

4.56 KB

app/assets/images/emoji/mushroom.png 0 → 100755

4.77 KB

app/assets/images/emoji/musical_keyboard.png 0 → 100755

1.9 KB

app/assets/images/emoji/musical_note.png 0 → 100755

3.11 KB

app/assets/images/emoji/musical_score.png 0 → 100755

1.54 KB

app/assets/images/emoji/mute.png 0 → 100755

6.48 KB

app/assets/images/emoji/nail_care.png 0 → 100755

5.68 KB

app/assets/images/emoji/name_badge.png 0 → 100755

3.89 KB

app/assets/images/emoji/neckbeard.png 0 → 100755

6.27 KB

app/assets/images/emoji/necktie.png 0 → 100755

5.97 KB

app/assets/images/emoji/negative_squared_cross_mark.png 0 → 100755

3.76 KB

app/assets/images/emoji/neutral_face.png 0 → 100755

4.73 KB

app/assets/images/emoji/new.png 0 → 100755

3.83 KB

app/assets/images/emoji/new_moon.png 0 → 100755

5.25 KB

app/assets/images/emoji/new_moon_with_face.png 0 → 100755

6.59 KB

app/assets/images/emoji/newspaper.png 0 → 100755

5.08 KB

app/assets/images/emoji/ng.png 0 → 100755

4.1 KB

app/assets/images/emoji/nine.png 0 → 100755

3.69 KB

app/assets/images/emoji/no_bell.png 0 → 100755

5.8 KB

app/assets/images/emoji/no_bicycles.png 0 → 100755

5.53 KB

app/assets/images/emoji/no_entry.png 0 → 100755

3.43 KB

app/assets/images/emoji/no_entry_sign.png 0 → 100755

3.21 KB

app/assets/images/emoji/no_good.png 0 → 100755

6.87 KB

app/assets/images/emoji/no_mobile_phones.png 0 → 100755

4.96 KB

app/assets/images/emoji/no_mouth.png 0 → 100755

4.62 KB

app/assets/images/emoji/no_pedestrians.png 0 → 100755

5.36 KB

app/assets/images/emoji/no_smoking.png 0 → 100755

4.11 KB

app/assets/images/emoji/non-potable_water.png 0 → 100755

5.08 KB

app/assets/images/emoji/nose.png 0 → 100755

3.62 KB

app/assets/images/emoji/notebook.png 0 → 100755

5.89 KB

app/assets/images/emoji/notebook_with_decorative_cover.png 0 → 100755

5.2 KB

app/assets/images/emoji/notes.png 0 → 100755

1.5 KB

app/assets/images/emoji/nut_and_bolt.png 0 → 100755

2.12 KB

app/assets/images/emoji/o.png 0 → 100755

2.48 KB

app/assets/images/emoji/o2.png 0 → 100755

3.42 KB

app/assets/images/emoji/ocean.png 0 → 100755

5.64 KB

app/assets/images/emoji/octocat.png 0 → 100755

3.84 KB

app/assets/images/emoji/octopus.png 0 → 100755

5.64 KB

app/assets/images/emoji/oden.png 0 → 100755

5.41 KB

app/assets/images/emoji/office.png 0 → 100755

5.04 KB

app/assets/images/emoji/ok.png 0 → 100755

4.06 KB

app/assets/images/emoji/ok_hand.png 0 → 100755

4.49 KB

app/assets/images/emoji/ok_woman.png 0 → 100755

7.35 KB

app/assets/images/emoji/older_man.png 0 → 100755

6.58 KB

app/assets/images/emoji/older_woman.png 0 → 100755

5.84 KB

app/assets/images/emoji/on.png 0 → 100755

1.76 KB

app/assets/images/emoji/oncoming_automobile.png 0 → 100755

7.29 KB

app/assets/images/emoji/oncoming_bus.png 0 → 100755

5.18 KB

app/assets/images/emoji/oncoming_police_car.png 0 → 100755

5.55 KB

app/assets/images/emoji/oncoming_taxi.png 0 → 100755

6.14 KB

app/assets/images/emoji/one.png 0 → 100755

2.76 KB

app/assets/images/emoji/open_file_folder.png 0 → 100755

4.19 KB

app/assets/images/emoji/open_hands.png 0 → 100755

4.83 KB

app/assets/images/emoji/ophiuchus.png 0 → 100755

4.33 KB

app/assets/images/emoji/orange_book.png 0 → 100755

4.97 KB

app/assets/images/emoji/outbox_tray.png 0 → 100755

3.6 KB

app/assets/images/emoji/ox.png 0 → 100755

5.94 KB

app/assets/images/emoji/page_facing_up.png 0 → 100755

2.13 KB

app/assets/images/emoji/page_with_curl.png 0 → 100755

3.64 KB

app/assets/images/emoji/pager.png 0 → 100755

3.93 KB

app/assets/images/emoji/palm_tree.png 0 → 100755

3.58 KB

app/assets/images/emoji/panda_face.png 0 → 100755

4.7 KB

app/assets/images/emoji/paperclip.png 0 → 100755

2.5 KB

app/assets/images/emoji/parking.png 0 → 100755

3.01 KB

app/assets/images/emoji/part_alternation_mark.png 0 → 100755

2.62 KB

app/assets/images/emoji/partly_sunny.png 0 → 100755

5.06 KB

app/assets/images/emoji/passport_control.png 0 → 100755

3.92 KB

app/assets/images/emoji/paw_prints.png 0 → 100755

2.41 KB

app/assets/images/emoji/peach.png 0 → 100755

5.78 KB

app/assets/images/emoji/pear.png 0 → 100755

6.77 KB

app/assets/images/emoji/pencil.png 0 → 100755

4.83 KB

app/assets/images/emoji/pencil2.png 0 → 100755

4.35 KB

app/assets/images/emoji/penguin.png 0 → 100755

4.63 KB

app/assets/images/emoji/pensive.png 0 → 100755

4.94 KB

app/assets/images/emoji/performing_arts.png 0 → 100755

6.14 KB

app/assets/images/emoji/persevere.png 0 → 100755

5.39 KB

app/assets/images/emoji/person_frowning.png 0 → 100755

4.71 KB

app/assets/images/emoji/person_with_blond_hair.png 0 → 100755

6.47 KB

app/assets/images/emoji/person_with_pouting_face.png 0 → 100755

5.3 KB

app/assets/images/emoji/phone.png 0 → 100755

5.37 KB

app/assets/images/emoji/pig.png 0 → 100755

5.86 KB

app/assets/images/emoji/pig2.png 0 → 100755

4.68 KB

app/assets/images/emoji/pig_nose.png 0 → 100755

4.65 KB

app/assets/images/emoji/pill.png 0 → 100755

4.9 KB

app/assets/images/emoji/pineapple.png 0 → 100755

5.5 KB

app/assets/images/emoji/pisces.png 0 → 100755

4.35 KB

app/assets/images/emoji/pizza.png 0 → 100755

5.15 KB

app/assets/images/emoji/plus1.png 0 → 100755

4.96 KB

app/assets/images/emoji/point_down.png 0 → 100755

3.15 KB

app/assets/images/emoji/point_left.png 0 → 100755

3.01 KB

app/assets/images/emoji/point_right.png 0 → 100755

3.01 KB

app/assets/images/emoji/point_up.png 0 → 100755

3.35 KB

app/assets/images/emoji/point_up_2.png 0 → 100755

3.11 KB

app/assets/images/emoji/police_car.png 0 → 100755

3.27 KB

app/assets/images/emoji/poodle.png 0 → 100755

6.69 KB

app/assets/images/emoji/poop.png 0 → 100755

4.64 KB

app/assets/images/emoji/post_office.png 0 → 100755

5.02 KB

app/assets/images/emoji/postal_horn.png 0 → 100755

4.71 KB

app/assets/images/emoji/postbox.png 0 → 100755

3.31 KB

app/assets/images/emoji/potable_water.png 0 → 100755

3.84 KB

app/assets/images/emoji/pouch.png 0 → 100755

4.58 KB

app/assets/images/emoji/poultry_leg.png 0 → 100755

4.1 KB

app/assets/images/emoji/pound.png 0 → 100755

4.14 KB

app/assets/images/emoji/pouting_cat.png 0 → 100755

4.8 KB

app/assets/images/emoji/pray.png 0 → 100755

6.06 KB

app/assets/images/emoji/princess.png 0 → 100755

7.73 KB

app/assets/images/emoji/punch.png 0 → 100755

4.72 KB

app/assets/images/emoji/purple_heart.png 0 → 100755

4.19 KB

app/assets/images/emoji/purse.png 0 → 100755

4.92 KB

app/assets/images/emoji/pushpin.png 0 → 100755

3.7 KB

app/assets/images/emoji/put_litter_in_its_place.png 0 → 100755

4 KB

app/assets/images/emoji/question.png 0 → 100755

1.67 KB

app/assets/images/emoji/rabbit.png 0 → 100755

5.54 KB

app/assets/images/emoji/rabbit2.png 0 → 100755

4.41 KB

app/assets/images/emoji/racehorse.png 0 → 100755

4.62 KB

app/assets/images/emoji/radio.png 0 → 100755

6.01 KB

app/assets/images/emoji/radio_button.png 0 → 100755

2.15 KB

app/assets/images/emoji/rage.png 0 → 100755

5.28 KB

app/assets/images/emoji/rage1.png 0 → 100755

1.06 KB

app/assets/images/emoji/rage2.png 0 → 100755

1.07 KB

app/assets/images/emoji/rage3.png 0 → 100755

1.09 KB

app/assets/images/emoji/rage4.png 0 → 100755

1.24 KB

app/assets/images/emoji/railway_car.png 0 → 100755

3.56 KB

app/assets/images/emoji/rainbow.png 0 → 100755

5.19 KB

app/assets/images/emoji/raised_hand.png 0 → 100755

6.03 KB

app/assets/images/emoji/raised_hands.png 0 → 100755

5.25 KB

app/assets/images/emoji/ram.png 0 → 100755

6.38 KB

app/assets/images/emoji/ramen.png 0 → 100755

6.42 KB

app/assets/images/emoji/rat.png 0 → 100755

5.31 KB

app/assets/images/emoji/recycle.png 0 → 100755

3.62 KB

app/assets/images/emoji/red_car.png 0 → 100755

4.18 KB

app/assets/images/emoji/red_circle.png 0 → 100755

3.85 KB

app/assets/images/emoji/registered.png 0 → 100755

1.58 KB

app/assets/images/emoji/relaxed.png 0 → 100755

5.33 KB

app/assets/images/emoji/relieved.png 0 → 100755

5.52 KB

app/assets/images/emoji/repeat.png 0 → 100755

3.92 KB

app/assets/images/emoji/repeat_one.png 0 → 100755

4.19 KB

app/assets/images/emoji/restroom.png 0 → 100755

4.04 KB

app/assets/images/emoji/revolving_hearts.png 0 → 100755

5.34 KB

app/assets/images/emoji/rewind.png 0 → 100755

2.98 KB

app/assets/images/emoji/ribbon.png 0 → 100755

5.45 KB

app/assets/images/emoji/rice.png 0 → 100755

4.54 KB

app/assets/images/emoji/rice_ball.png 0 → 100755

5.28 KB

app/assets/images/emoji/rice_cracker.png 0 → 100755

7.6 KB

app/assets/images/emoji/rice_scene.png 0 → 100755

6.11 KB

app/assets/images/emoji/ring.png 0 → 100755

5.11 KB

app/assets/images/emoji/rocket.png 0 → 100755

5.26 KB

app/assets/images/emoji/roller_coaster.png 0 → 100755

5.03 KB

app/assets/images/emoji/rooster.png 0 → 100755

6.02 KB

app/assets/images/emoji/rose.png 0 → 100755

4.1 KB

app/assets/images/emoji/rotating_light.png 0 → 100755

6.46 KB

app/assets/images/emoji/round_pushpin.png 0 → 100755

1.89 KB

app/assets/images/emoji/rowboat.png 0 → 100755

5.31 KB

app/assets/images/emoji/ru.png 0 → 100755

3.83 KB

app/assets/images/emoji/rugby_football.png 0 → 100755

7.6 KB

app/assets/images/emoji/runner.png 0 → 100755

3.06 KB

app/assets/images/emoji/running.png 0 → 100755

3.14 KB

app/assets/images/emoji/running_shirt_with_sash.png 0 → 100755

5.57 KB

app/assets/images/emoji/sa.png 0 → 100755

3.47 KB

app/assets/images/emoji/sagittarius.png 0 → 100755

4.4 KB

app/assets/images/emoji/sailboat.png 0 → 100755

3.74 KB

app/assets/images/emoji/sake.png 0 → 100755

4.95 KB

app/assets/images/emoji/sandal.png 0 → 100755

3.88 KB

app/assets/images/emoji/santa.png 0 → 100755

6.12 KB

app/assets/images/emoji/satellite.png 0 → 100755

4.75 KB

app/assets/images/emoji/satisfied.png 0 → 100755

5.24 KB

app/assets/images/emoji/saxophone.png 0 → 100755

4.15 KB

app/assets/images/emoji/school.png 0 → 100755

5.32 KB

app/assets/images/emoji/school_satchel.png 0 → 100755

5.61 KB

app/assets/images/emoji/scissors.png 0 → 100755

3.75 KB

app/assets/images/emoji/scorpius.png 0 → 100755

4.46 KB

app/assets/images/emoji/scream.png 0 → 100755

6.33 KB

app/assets/images/emoji/scream_cat.png 0 → 100755

6.68 KB

app/assets/images/emoji/scroll.png 0 → 100755

6.59 KB

app/assets/images/emoji/seat.png 0 → 100755

5.92 KB

app/assets/images/emoji/secret.png 0 → 100755

5.24 KB

app/assets/images/emoji/see_no_evil.png 0 → 100755

6.67 KB

app/assets/images/emoji/seedling.png 0 → 100755

2.21 KB

app/assets/images/emoji/seven.png 0 → 100755

2.98 KB

app/assets/images/emoji/shaved_ice.png 0 → 100755

5.77 KB

app/assets/images/emoji/sheep.png 0 → 100755

4.62 KB

app/assets/images/emoji/shell.png 0 → 100755

5 KB

app/assets/images/emoji/ship.png 0 → 100755

4.13 KB

app/assets/images/emoji/shipit.png 0 → 100755

9.13 KB

app/assets/images/emoji/shirt.png 0 → 100755

4.57 KB

app/assets/images/emoji/shit.png 0 → 100755

4.64 KB

app/assets/images/emoji/shoe.png 0 → 100755

4.69 KB

app/assets/images/emoji/shower.png 0 → 100755

7.41 KB

app/assets/images/emoji/signal_strength.png 0 → 100755

3.16 KB

app/assets/images/emoji/six.png 0 → 100755

3.7 KB

app/assets/images/emoji/six_pointed_star.png 0 → 100755

4.75 KB

app/assets/images/emoji/ski.png 0 → 100755

4.07 KB

app/assets/images/emoji/skull.png 0 → 100755

2.37 KB

app/assets/images/emoji/sleepy.png 0 → 100755

5.7 KB

app/assets/images/emoji/slot_machine.png 0 → 100755

4.5 KB

app/assets/images/emoji/small_blue_diamond.png 0 → 100755

1.85 KB

app/assets/images/emoji/small_orange_diamond.png 0 → 100755

1.9 KB

app/assets/images/emoji/small_red_triangle.png 0 → 100755

2.01 KB

app/assets/images/emoji/small_red_triangle_down.png 0 → 100755

2.11 KB

app/assets/images/emoji/smile.png 0 → 100755

5.75 KB

app/assets/images/emoji/smile_cat.png 0 → 100755

5.97 KB

app/assets/images/emoji/smiley.png 0 → 100755

5.66 KB

app/assets/images/emoji/smiley_cat.png 0 → 100755

5.94 KB

app/assets/images/emoji/smiling_imp.png 0 → 100755

7.02 KB

app/assets/images/emoji/smirk.png 0 → 100755

5.18 KB

app/assets/images/emoji/smirk_cat.png 0 → 100755

5.92 KB

app/assets/images/emoji/smoking.png 0 → 100755

2.81 KB

app/assets/images/emoji/snail.png 0 → 100755

6.5 KB

app/assets/images/emoji/snake.png 0 → 100755

3.97 KB

app/assets/images/emoji/snowboarder.png 0 → 100755

5.23 KB

app/assets/images/emoji/snowflake.png 0 → 100755

5.5 KB

app/assets/images/emoji/snowman.png 0 → 100755

4.55 KB

app/assets/images/emoji/sob.png 0 → 100755

5.58 KB

app/assets/images/emoji/soccer.png 0 → 100755

4.76 KB

app/assets/images/emoji/soon.png 0 → 100755

1.87 KB

app/assets/images/emoji/sos.png 0 → 100755

4.16 KB

app/assets/images/emoji/sound.png 0 → 100755

4.91 KB

app/assets/images/emoji/space_invader.png 0 → 100755

4.25 KB

app/assets/images/emoji/spades.png 0 → 100755

1.68 KB

app/assets/images/emoji/spaghetti.png 0 → 100755

6.79 KB

app/assets/images/emoji/sparkler.png 0 → 100755

5.56 KB

app/assets/images/emoji/sparkles.png 0 → 100755

2.16 KB

app/assets/images/emoji/speak_no_evil.png 0 → 100755

5.84 KB

app/assets/images/emoji/speaker.png 0 → 100755

5.05 KB

app/assets/images/emoji/speech_balloon.png 0 → 100755

2.08 KB

app/assets/images/emoji/speedboat.png 0 → 100755

3.43 KB

app/assets/images/emoji/squirrel.png 0 → 100755

9.13 KB

app/assets/images/emoji/star.png 0 → 100755

3.54 KB

app/assets/images/emoji/star2.png 0 → 100755

3.97 KB

app/assets/images/emoji/stars.png 0 → 100755

4.26 KB

app/assets/images/emoji/station.png 0 → 100755

4.72 KB

app/assets/images/emoji/statue_of_liberty.png 0 → 100755

5.93 KB

app/assets/images/emoji/steam_locomotive.png 0 → 100755

5.04 KB

app/assets/images/emoji/stew.png 0 → 100755

5.24 KB

app/assets/images/emoji/straight_ruler.png 0 → 100755

3.74 KB

app/assets/images/emoji/strawberry.png 0 → 100755

5.35 KB

app/assets/images/emoji/sun_with_face.png 0 → 100755

7.77 KB

app/assets/images/emoji/sunflower.png 0 → 100755

6.41 KB

app/assets/images/emoji/sunglasses.png 0 → 100755

5.61 KB

app/assets/images/emoji/sunny.png 0 → 100755

3.71 KB

app/assets/images/emoji/sunrise.png 0 → 100755

3.82 KB

app/assets/images/emoji/sunrise_over_mountains.png 0 → 100755

6.44 KB

app/assets/images/emoji/surfer.png 0 → 100755

6.11 KB

app/assets/images/emoji/sushi.png 0 → 100755

5.13 KB

app/assets/images/emoji/suspect.png 0 → 100755

1016 Bytes

app/assets/images/emoji/suspension_railway.png 0 → 100755

3.84 KB

app/assets/images/emoji/sweat.png 0 → 100755

5.45 KB

app/assets/images/emoji/sweat_drops.png 0 → 100755

4.67 KB

app/assets/images/emoji/sweat_smile.png 0 → 100755

6.37 KB

app/assets/images/emoji/sweet_potato.png 0 → 100755

5.55 KB

app/assets/images/emoji/swimmer.png 0 → 100755

4.28 KB

app/assets/images/emoji/symbols.png 0 → 100755

5.31 KB

app/assets/images/emoji/syringe.png 0 → 100755

2.97 KB

app/assets/images/emoji/tada.png 0 → 100755

5.81 KB

app/assets/images/emoji/tanabata_tree.png 0 → 100755

4.31 KB

app/assets/images/emoji/tangerine.png 0 → 100755

6.49 KB

app/assets/images/emoji/taurus.png 0 → 100755

4.62 KB

app/assets/images/emoji/taxi.png 0 → 100755

3.66 KB

app/assets/images/emoji/tea.png 0 → 100755

5.81 KB

app/assets/images/emoji/telephone.png 0 → 100755

5.37 KB

app/assets/images/emoji/telephone_receiver.png 0 → 100755

1.95 KB

app/assets/images/emoji/telescope.png 0 → 100755

3.24 KB

app/assets/images/emoji/tennis.png 0 → 100755

5.84 KB

app/assets/images/emoji/tent.png 0 → 100755

4.38 KB

app/assets/images/emoji/thought_balloon.png 0 → 100755

2.52 KB

app/assets/images/emoji/three.png 0 → 100755

3.67 KB

app/assets/images/emoji/thumbsdown.png 0 → 100755

4.95 KB

app/assets/images/emoji/thumbsup.png 0 → 100755

4.96 KB

app/assets/images/emoji/ticket.png 0 → 100755

3.02 KB

app/assets/images/emoji/tiger.png 0 → 100755

5.91 KB

app/assets/images/emoji/tiger2.png 0 → 100755

5.61 KB

app/assets/images/emoji/tired_face.png 0 → 100755

6.03 KB

app/assets/images/emoji/tm.png 0 → 100755

842 Bytes

app/assets/images/emoji/toilet.png 0 → 100755

1.69 KB

app/assets/images/emoji/tokyo_tower.png 0 → 100755

4.69 KB

app/assets/images/emoji/tomato.png 0 → 100755

5.61 KB

app/assets/images/emoji/tongue.png 0 → 100755

5.65 KB

app/assets/images/emoji/tongue2.png 0 → 100755

3.58 KB

app/assets/images/emoji/top.png 0 → 100755

3.7 KB

app/assets/images/emoji/tophat.png 0 → 100755

2.94 KB

app/assets/images/emoji/tractor.png 0 → 100755

5.54 KB

app/assets/images/emoji/traffic_light.png 0 → 100755

3.46 KB

app/assets/images/emoji/train.png 0 → 100755

3.81 KB

app/assets/images/emoji/train2.png 0 → 100755

4.7 KB

app/assets/images/emoji/tram.png 0 → 100755

4.75 KB

app/assets/images/emoji/triangular_flag_on_post.png 0 → 100755

1.37 KB

app/assets/images/emoji/triangular_ruler.png 0 → 100755

2.64 KB

app/assets/images/emoji/trident.png 0 → 100755

4.72 KB

app/assets/images/emoji/triumph.png 0 → 100755

6.02 KB

app/assets/images/emoji/trolleybus.png 0 → 100755

4.33 KB

app/assets/images/emoji/trollface.png 0 → 100755

4.79 KB

app/assets/images/emoji/trophy.png 0 → 100755

5.39 KB

app/assets/images/emoji/tropical_drink.png 0 → 100755

4.09 KB

app/assets/images/emoji/tropical_fish.png 0 → 100755

5.71 KB

app/assets/images/emoji/truck.png 0 → 100755

3.63 KB

app/assets/images/emoji/trumpet.png 0 → 100755

4.27 KB

app/assets/images/emoji/tshirt.png 0 → 100755

4.57 KB

app/assets/images/emoji/tulip.png 0 → 100755

5.92 KB

app/assets/images/emoji/turtle.png 0 → 100755

5.21 KB

app/assets/images/emoji/tv.png 0 → 100755

5.12 KB

app/assets/images/emoji/twisted_rightwards_arrows.png 0 → 100755

4.21 KB

app/assets/images/emoji/two.png 0 → 100755

3.44 KB

app/assets/images/emoji/two_hearts.png 0 → 100755

3.48 KB

app/assets/images/emoji/two_men_holding_hands.png 0 → 100755

6.83 KB

app/assets/images/emoji/two_women_holding_hands.png 0 → 100755

7.45 KB

app/assets/images/emoji/u5272.png 0 → 100755

4.43 KB

app/assets/images/emoji/u5408.png 0 → 100755

3.8 KB

app/assets/images/emoji/u55b6.png 0 → 100755

3.33 KB

app/assets/images/emoji/u6307.png 0 → 100755

4.01 KB

app/assets/images/emoji/u6708.png 0 → 100755

2.94 KB

app/assets/images/emoji/u6709.png 0 → 100755

3.12 KB

app/assets/images/emoji/u6e80.png 0 → 100755

4.32 KB

app/assets/images/emoji/u7121.png 0 → 100755

3.85 KB

app/assets/images/emoji/u7533.png 0 → 100755

2.98 KB

app/assets/images/emoji/u7981.png 0 → 100755

5.05 KB

app/assets/images/emoji/u7a7a.png 0 → 100755

4.08 KB

app/assets/images/emoji/uk.png 0 → 100755

5.76 KB

app/assets/images/emoji/umbrella.png 0 → 100755

4.63 KB

app/assets/images/emoji/unamused.png 0 → 100755

5.19 KB

app/assets/images/emoji/underage.png 0 → 100755

5.59 KB

app/assets/images/emoji/unlock.png 0 → 100755

3.47 KB

app/assets/images/emoji/up.png 0 → 100755

3.63 KB

app/assets/images/emoji/us.png 0 → 100755

6.14 KB

app/assets/images/emoji/v.png 0 → 100755

4.56 KB

app/assets/images/emoji/vertical_traffic_light.png 0 → 100755

3.34 KB

app/assets/images/emoji/vhs.png 0 → 100755

3.07 KB

app/assets/images/emoji/vibration_mode.png 0 → 100755

3.81 KB

app/assets/images/emoji/video_camera.png 0 → 100755

4.97 KB

app/assets/images/emoji/video_game.png 0 → 100755

4.84 KB

app/assets/images/emoji/violin.png 0 → 100755

4.9 KB

app/assets/images/emoji/virgo.png 0 → 100755

4.75 KB

app/assets/images/emoji/volcano.png 0 → 100755

6.02 KB

app/assets/images/emoji/vs.png 0 → 100755

3.34 KB

app/assets/images/emoji/walking.png 0 → 100755

2.41 KB

app/assets/images/emoji/waning_crescent_moon.png 0 → 100755

5.75 KB

app/assets/images/emoji/waning_gibbous_moon.png 0 → 100755

6.36 KB

app/assets/images/emoji/warning.png 0 → 100755

3.1 KB

app/assets/images/emoji/watch.png 0 → 100755

5.07 KB

app/assets/images/emoji/water_buffalo.png 0 → 100755

4.66 KB

app/assets/images/emoji/watermelon.png 0 → 100755

5.37 KB

app/assets/images/emoji/wave.png 0 → 100755

4.93 KB

app/assets/images/emoji/wavy_dash.png 0 → 100755

872 Bytes

app/assets/images/emoji/waxing_crescent_moon.png 0 → 100755

6.05 KB

app/assets/images/emoji/waxing_gibbous_moon.png 0 → 100755

6.3 KB

app/assets/images/emoji/wc.png 0 → 100755

3.99 KB

app/assets/images/emoji/weary.png 0 → 100755

6.13 KB

app/assets/images/emoji/wedding.png 0 → 100755

5.71 KB

app/assets/images/emoji/whale.png 0 → 100755

4.82 KB

app/assets/images/emoji/whale2.png 0 → 100755

5.89 KB

app/assets/images/emoji/wheelchair.png 0 → 100755

4.13 KB

app/assets/images/emoji/white_circle.png 0 → 100755

2.45 KB

app/assets/images/emoji/white_flower.png 0 → 100755

4.29 KB

app/assets/images/emoji/white_square.png 0 → 100755

1.38 KB

app/assets/images/emoji/wind_chime.png 0 → 100755

3.41 KB

app/assets/images/emoji/wine_glass.png 0 → 100755

3.08 KB

app/assets/images/emoji/wink.png 0 → 100755

5.13 KB

app/assets/images/emoji/wink2.png 0 → 100755

5.87 KB

app/assets/images/emoji/wolf.png 0 → 100755

4.73 KB

app/assets/images/emoji/woman.png 0 → 100755

6.73 KB

app/assets/images/emoji/womans_clothes.png 0 → 100755

3.98 KB

app/assets/images/emoji/womans_hat.png 0 → 100755

7.91 KB

app/assets/images/emoji/womens.png 0 → 100755

3.8 KB

app/assets/images/emoji/wrench.png 0 → 100755

2.71 KB

app/assets/images/emoji/x.png 0 → 100755

2 KB

app/assets/images/emoji/yellow_heart.png 0 → 100755

4.31 KB

app/assets/images/emoji/yen.png 0 → 100755

4.87 KB

app/assets/images/emoji/yum.png 0 → 100755

5.75 KB

app/assets/images/emoji/zap.png 0 → 100755

2.18 KB

app/assets/images/emoji/zero.png 0 → 100755

3.51 KB

app/assets/images/emoji/zzz.png 0 → 100755

1.98 KB

app/assets/javascripts/admin.js
... ... @@ -1,11 +0,0 @@
1   -$(document).ready(function(){
2   - $('input#user_force_random_password').on('change', function(elem) {
3   - var elems = $('#user_password, #user_password_confirmation');
4   -
5   - if ($(this).attr('checked')) {
6   - elems.val('').attr('disabled', true);
7   - } else {
8   - elems.removeAttr('disabled');
9   - }
10   - });
11   -});
app/assets/javascripts/admin.js.coffee 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +$ ->
  2 + $('input#user_force_random_password').on 'change', (elem) ->
  3 + elems = $('#user_password, #user_password_confirmation')
  4 +
  5 + if $(@).attr 'checked'
  6 + elems.val('').attr 'disabled', true
  7 + else
  8 + elems.removeAttr 'disabled'
... ...
app/assets/javascripts/application.js
... ... @@ -17,134 +17,3 @@
17 17 //= require raphael
18 18 //= require branch-graph
19 19 //= require_tree .
20   -
21   -$(document).ready(function(){
22   -
23   - $(".one_click_select").live("click", function(){
24   - $(this).select();
25   - });
26   -
27   - $('body').on('ajax:complete, ajax:beforeSend, submit', 'form', function(e){
28   - var buttons = $('[type="submit"]', this);
29   - switch( e.type ){
30   - case 'ajax:beforeSend':
31   - case 'submit':
32   - buttons.attr('disabled', 'disabled');
33   - break;
34   - case ' ajax:complete':
35   - default:
36   - buttons.removeAttr('disabled');
37   - break;
38   - }
39   - })
40   -
41   - $(".account-box").mouseenter(showMenu);
42   - $(".account-box").mouseleave(resetMenu);
43   -
44   - $("#projects-list .project").live('click', function(e){
45   - if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") {
46   - location.href = $(this).attr("url");
47   - e.stopPropagation();
48   - return false;
49   - }
50   - });
51   -
52   - /**
53   - * Focus search field by pressing 's' key
54   - */
55   - $(document).keypress(function(e) {
56   - if( $(e.target).is(":input") ) return;
57   - switch(e.which) {
58   - case 115: focusSearch();
59   - e.preventDefault();
60   - }
61   - });
62   -
63   - /**
64   - * Commit show suppressed diff
65   - *
66   - */
67   - $(".supp_diff_link").bind("click", function() {
68   - showDiff(this);
69   - });
70   -
71   - /**
72   - * Note markdown preview
73   - *
74   - */
75   - $(document).on('click', '#preview-link', function(e) {
76   - $('#preview-note').text('Loading...');
77   -
78   - var previewLinkText = ($(this).text() == 'Preview' ? 'Edit' : 'Preview');
79   - $(this).text(previewLinkText);
80   -
81   - var note = $('#note_note').val();
82   - if (note.trim().length === 0) { note = 'Nothing to preview'; }
83   - $.post($(this).attr('href'), {note: note}, function(data) {
84   - $('#preview-note').html(data);
85   - });
86   -
87   - $('#preview-note, #note_note').toggle();
88   - e.preventDefault();
89   - });
90   -});
91   -
92   -function focusSearch() {
93   - $("#search").focus();
94   -}
95   -
96   -function updatePage(data){
97   - $.ajax({type: "GET", url: location.href, data: data, dataType: "script"});
98   -}
99   -
100   -function showMenu() {
101   - $(this).toggleClass('hover');
102   -}
103   -
104   -function resetMenu() {
105   - $(this).removeClass("hover");
106   -}
107   -
108   -function slugify(text) {
109   - return text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase();
110   -}
111   -
112   -function showDiff(link) {
113   - $(link).next('table').show();
114   - $(link).remove();
115   -}
116   -
117   -(function($){
118   - var _chosen = $.fn.chosen;
119   - $.fn.extend({
120   - chosen: function(options) {
121   - var default_options = {'search_contains' : 'true'};
122   - $.extend(default_options, options);
123   - return _chosen.apply(this, [default_options]);
124   - }})
125   -})(jQuery);
126   -
127   -
128   -function ajaxGet(url) {
129   - $.ajax({type: "GET", url: url, dataType: "script"});
130   -}
131   -
132   -/**
133   - * Disable button if text field is empty
134   - */
135   -function disableButtonIfEmtpyField(field_selector, button_selector) {
136   - field = $(field_selector);
137   - if(field.val() == "") {
138   - field.closest("form").find(button_selector).attr("disabled", "disabled").addClass("disabled");
139   - }
140   -
141   - field.on('keyup', function(){
142   - var field = $(this);
143   - var closest_submit = field.closest("form").find(button_selector);
144   - if(field.val() == "") {
145   - closest_submit.attr("disabled", "disabled").addClass("disabled");
146   - } else {
147   - closest_submit.removeAttr("disabled").removeClass("disabled");
148   - }
149   - })
150   -}
... ...
app/assets/javascripts/graph.js
... ... @@ -1,10 +0,0 @@
1   -function initGraphNav() {
2   - $(".graph svg").css("position", "relative");
3   - $("body").bind("keyup", function(e) {
4   - if(e.keyCode == 37) { // left
5   - $(".graph svg").animate({ left: "+=400" });
6   - } else if(e.keyCode == 39) { // right
7   - $(".graph svg").animate({ left: "-=400" });
8   - }
9   - });
10   -}
app/assets/javascripts/graph.js.coffee 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +initGraphNav = ->
  2 + $('.graph svg').css 'position', 'relative'
  3 +
  4 + $('body').bind 'keyup', (e) ->
  5 + if e.keyCode is 37 # left
  6 + $('.graph svg').animate left: '+=400'
  7 + else if e.keyCode is 39 # right
  8 + $('.graph svg').animate left: '-=400'
  9 +
  10 +window.initGraphNav = initGraphNav
... ...
app/assets/javascripts/loader.js
... ... @@ -1,11 +0,0 @@
1   -var Loader = {
2   - img_src: "/assets/ajax-loader.gif",
3   -
4   - html:
5   - function(width) {
6   - img = $("<img>");
7   - img.attr("width", width);
8   - img.attr("src", this.img_src);
9   - return img;
10   - }
11   -}
app/assets/javascripts/loader.js.coffee 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +Loader =
  2 + html: (width) ->
  3 + $('<img>').attr src: '/assets/ajax-loader.gif', width: width
  4 +
  5 +window.Loader = Loader
... ...
app/assets/javascripts/main.js 0 → 100644
... ... @@ -0,0 +1,130 @@
  1 +$(document).ready(function(){
  2 +
  3 + $(".one_click_select").live("click", function(){
  4 + $(this).select();
  5 + });
  6 +
  7 + $('body').on('ajax:complete, ajax:beforeSend, submit', 'form', function(e){
  8 + var buttons = $('[type="submit"]', this);
  9 + switch( e.type ){
  10 + case 'ajax:beforeSend':
  11 + case 'submit':
  12 + buttons.attr('disabled', 'disabled');
  13 + break;
  14 + case ' ajax:complete':
  15 + default:
  16 + buttons.removeAttr('disabled');
  17 + break;
  18 + }
  19 + })
  20 +
  21 + $(".account-box").mouseenter(showMenu);
  22 + $(".account-box").mouseleave(resetMenu);
  23 +
  24 + $("#projects-list .project").live('click', function(e){
  25 + if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") {
  26 + location.href = $(this).attr("url");
  27 + e.stopPropagation();
  28 + return false;
  29 + }
  30 + });
  31 +
  32 + /**
  33 + * Focus search field by pressing 's' key
  34 + */
  35 + $(document).keypress(function(e) {
  36 + if( $(e.target).is(":input") ) return;
  37 + switch(e.which) {
  38 + case 115: focusSearch();
  39 + e.preventDefault();
  40 + }
  41 + });
  42 +
  43 + /**
  44 + * Commit show suppressed diff
  45 + *
  46 + */
  47 + $(".supp_diff_link").bind("click", function() {
  48 + showDiff(this);
  49 + });
  50 +
  51 + /**
  52 + * Note markdown preview
  53 + *
  54 + */
  55 + $(document).on('click', '#preview-link', function(e) {
  56 + $('#preview-note').text('Loading...');
  57 +
  58 + var previewLinkText = ($(this).text() == 'Preview' ? 'Edit' : 'Preview');
  59 + $(this).text(previewLinkText);
  60 +
  61 + var note = $('#note_note').val();
  62 + if (note.trim().length === 0) { note = 'Nothing to preview'; }
  63 + $.post($(this).attr('href'), {note: note}, function(data) {
  64 + $('#preview-note').html(data);
  65 + });
  66 +
  67 + $('#preview-note, #note_note').toggle();
  68 + e.preventDefault();
  69 + });
  70 +});
  71 +
  72 +function focusSearch() {
  73 + $("#search").focus();
  74 +}
  75 +
  76 +function updatePage(data){
  77 + $.ajax({type: "GET", url: location.href, data: data, dataType: "script"});
  78 +}
  79 +
  80 +function showMenu() {
  81 + $(this).toggleClass('hover');
  82 +}
  83 +
  84 +function resetMenu() {
  85 + $(this).removeClass("hover");
  86 +}
  87 +
  88 +function slugify(text) {
  89 + return text.replace(/[^-a-zA-Z0-9]+/g, '_').toLowerCase();
  90 +}
  91 +
  92 +function showDiff(link) {
  93 + $(link).next('table').show();
  94 + $(link).remove();
  95 +}
  96 +
  97 +(function($){
  98 + var _chosen = $.fn.chosen;
  99 + $.fn.extend({
  100 + chosen: function(options) {
  101 + var default_options = {'search_contains' : 'true'};
  102 + $.extend(default_options, options);
  103 + return _chosen.apply(this, [default_options]);
  104 + }})
  105 +})(jQuery);
  106 +
  107 +
  108 +function ajaxGet(url) {
  109 + $.ajax({type: "GET", url: url, dataType: "script"});
  110 +}
  111 +
  112 +/**
  113 + * Disable button if text field is empty
  114 + */
  115 +function disableButtonIfEmtpyField(field_selector, button_selector) {
  116 + field = $(field_selector);
  117 + if(field.val() == "") {
  118 + field.closest("form").find(button_selector).attr("disabled", "disabled").addClass("disabled");
  119 + }
  120 +
  121 + field.on('keyup', function(){
  122 + var field = $(this);
  123 + var closest_submit = field.closest("form").find(button_selector);
  124 + if(field.val() == "") {
  125 + closest_submit.attr("disabled", "disabled").addClass("disabled");
  126 + } else {
  127 + closest_submit.removeAttr("disabled").removeClass("disabled");
  128 + }
  129 + })
  130 +}
... ...
app/assets/javascripts/projects.js
... ... @@ -1,16 +0,0 @@
1   -function Projects() {
2   - $("#project_name").live("change", function(){
3   - var slug = slugify($(this).val());
4   - $("#project_code").val(slug);
5   - $("#project_path").val(slug);
6   - });
7   -
8   - $('.new_project, .edit_project').live('ajax:before', function() {
9   - $('.project_new_holder, .project_edit_holder').hide();
10   - $('.save-project-loader').show();
11   - });
12   -
13   - $('form #project_default_branch').chosen();
14   -
15   - disableButtonIfEmtpyField("#project_name", ".project-submit")
16   -}
app/assets/javascripts/projects.js.coffee 0 → 100644
... ... @@ -0,0 +1,20 @@
  1 +window.Projects = ->
  2 + $('#project_name').on 'change', ->
  3 + slug = slugify $(@).val()
  4 + $('#project_code, #project_path').val slug
  5 +
  6 + $('.new_project, .edit_project').on 'ajax:before', ->
  7 + $('.project_new_holder, .project_edit_holder').hide()
  8 + $('.save-project-loader').show()
  9 +
  10 + $('form #project_default_branch').chosen()
  11 + disableButtonIfEmtpyField '#project_name', '.project-submit'
  12 +
  13 +# Git clone panel switcher
  14 +$ ->
  15 + scope = $ '.project_clone_holder'
  16 + if scope.length > 0
  17 + $('a, button', scope).click ->
  18 + $('a, button', scope).removeClass 'active'
  19 + $(@).addClass 'active'
  20 + $('#project_clone', scope).val $(@).data 'clone'
... ...
app/assets/javascripts/snippets.js
... ... @@ -1,9 +0,0 @@
1   -$(document).ready(function(){
2   - $("#snippets-table .snippet").live('click', function(e){
3   - if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") {
4   - location.href = $(this).attr("url");
5   - e.stopPropagation();
6   - return false;
7   - }
8   - });
9   -});
app/assets/javascripts/snippets.js.coffee 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +$ ->
  2 + $('#snippets-table .snippet').live 'click', (e) ->
  3 + if e.target.nodeName isnt 'A' and e.target.nodeName isnt 'INPUT'
  4 + location.href = $(@).attr 'url'
  5 + e.stopPropagation()
  6 + false
... ...
app/assets/javascripts/team.js
... ... @@ -1,8 +0,0 @@
1   -function backToMembers(){
2   - $("#new_team_member").hide("slide", { direction: "right" }, 150, function(){
3   - $("#team-table").show("slide", { direction: "left" }, 150, function() {
4   - $("#new_team_member").remove();
5   - $(".add_new").show();
6   - });
7   - });
8   -}
app/assets/stylesheets/gitlab_bootstrap/blocks.scss
1 1 /**
2 2 * ===================================
3   - * Contain 3 main UI block elements:
  3 + * Contain 3 main UI block elements:
4 4 * .main_box - for show pages
5 5 * .ui-box - for simple block & widgets
6 6 * ===================================
... ...
app/assets/stylesheets/gitlab_bootstrap/buttons.scss
1 1 .btn {
2   - background-image: -webkit-gradient(linear, 0 0, 0 26, color-stop(0.076, #f7f7f7), to(#d5d5d5));
3   - background-image: -webkit-linear-gradient(#f7f7f7 7.6%, #d5d5d5);
4   - background-image: -moz-linear-gradient(#f7f7f7 7.6%, #d5d5d5);
5   - background-image: -o-linear-gradient(#f7f7f7 7.6%, #d5d5d5);
  2 + @include bg-gradient(#f7f7f7, #d5d5d5);
6 3 border-color:#aaa;
7 4 &:hover {
8 5 @include bg-gray-gradient;
... ... @@ -12,10 +9,8 @@
12 9  
13 10 &.primary {
14 11 background:#2a79A3;
  12 + @include bg-gradient(#47A7b7, #2585b5);
15 13 border-color: #2A79A3;
16   - background-image: -webkit-linear-gradient(#47A7b7 7.6%, #2585b5);
17   - background-image: -moz-linear-gradient(#47A7b7 7.6%, #2585b5);
18   - background-image: -o-linear-gradient(#47A7b7 7.6%, #2585b5);
19 14 color:#fff;
20 15 text-shadow: 0 1px 1px #268;
21 16 &:hover {
... ... @@ -30,16 +25,11 @@
30 25 }
31 26  
32 27 &.success {
33   - border-color: #4A4;
34   - background-image: -webkit-linear-gradient(#82D482 7.6%, #22B442);
35   - background-image: -moz-linear-gradient(#82D482 7.6%, #22B442);
36   - background-image: -o-linear-gradient(#82D482 7.6%, #22B442);
37   - color: #fff;
38   - text-shadow: 0 1px 1px #141;
  28 + @extend .btn-success;
39 29  
40 30 &:hover {
41   - background: #6C6;
42   - color: #fff;
  31 + @extend .btn-success;
  32 + background: #51a351;
43 33 }
44 34  
45 35 &.disabled {
... ... @@ -62,10 +52,8 @@
62 52 padding-right:30px;
63 53 }
64 54  
65   - &.danger,
66   - &.btn-danger {
67   - color:#fff;
68   - background: #DA4E49;
  55 + &.danger {
  56 + @extend .btn-danger;
69 57 border-color: #BD362F;
70 58  
71 59 &:hover {
... ...
app/assets/stylesheets/gitlab_bootstrap/files.scss
... ... @@ -3,13 +3,13 @@
3 3 *
4 4 */
5 5 .file_holder {
6   - border:1px solid #CCC;
  6 + border:1px solid #BBB;
7 7 margin-bottom:1em;
8 8 @include solid_shade;
9 9  
10 10 .file_title {
11 11 border-bottom: 1px solid #bbb;
12   - @include bg-gray-gradient;
  12 + @include bg-dark-gray-gradient;
13 13 margin: 0;
14 14 font-weight: normal;
15 15 font-weight: bold;
... ...
app/assets/stylesheets/highlight/white.scss
1   -table.highlighttable
2   -{
  1 +table.highlighttable {
3 2 margin:0px;
4 3 padding:0px;
5 4 font-size:12px;
6 5 table-layout:fixed;
7 6 background: #EEE;
  7 + box-shadow: none;
  8 + border: none;
  9 + td.linenos {
  10 + background:#eee;
  11 + border-left:none;
  12 + }
  13 + td.code {
  14 + border-right:none;
  15 + }
8 16 }
9 17  
  18 +
10 19 td.code,
11 20 td.linenos{
12 21 padding:0;
... ...
app/assets/stylesheets/main.scss
1 1 @import "bootstrap";
2 2 @import "bootstrap-responsive";
3 3  
4   -/** GITLAB colors **/
  4 +/** GitLab colors **/
5 5 $link_color:#3A89A3;
6 6 $blue_link: #2fa0bb;
7 7 $style_color: #474d57;
8 8 $hover: #fdf5d9;
9 9  
10   -/** GITLAB Fonts **/
  10 +/** GitLab Fonts **/
11 11 @font-face { font-family: Korolev; src: url('korolev-medium-compressed.otf'); }
12 12  
13 13 /** MIXINS **/
... ... @@ -56,6 +56,13 @@ $hover: #fdf5d9;
56 56 border-radius: $radius;
57 57 }
58 58  
  59 +@mixin bg-gradient($from, $to) {
  60 + background-image: -webkit-gradient(linear, 0 0, 0 100%, from($from), to($to));
  61 + background-image: -webkit-linear-gradient($from, $to);
  62 + background-image: -moz-linear-gradient($from, $to);
  63 + background-image: -o-linear-gradient($from, $to);
  64 +}
  65 +
59 66 @mixin bg-gray-gradient {
60 67 background:#eee;
61 68 background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
... ... @@ -106,9 +113,9 @@ $hover: #fdf5d9;
106 113 @import "themes/ui_modern.scss";
107 114  
108 115 /**
109   - * Gitlab bootstrap.
  116 + * GitLab bootstrap.
110 117 * Overrides some styles of twitter bootstrap.
111   - * Also give some common classes for gitlab app
  118 + * Also give some common classes for GitLab app
112 119 */
113 120 @import "gitlab_bootstrap/common.scss";
114 121 @import "gitlab_bootstrap/typography.scss";
... ...
app/assets/stylesheets/sections/header.scss
... ... @@ -22,7 +22,7 @@ header {
22 22 *
23 23 */
24 24 .app_logo {
25   - width:230px;
  25 + width:200px;
26 26 float:left;
27 27 position:relative;
28 28 top:-5px;
... ... @@ -31,7 +31,7 @@ header {
31 31  
32 32 h1 {
33 33 padding-top: 5px;
34   - width:102px;
  34 + width:90px;
35 35 background: url('logo_dark.png') no-repeat 0px -3px;
36 36 float:left;
37 37 margin-left:5px;
... ...
app/assets/stylesheets/sections/nav.scss
... ... @@ -2,7 +2,7 @@
2 2 * Main Menu of Application
3 3 *
4 4 */
5   -ul.main_menu {
  5 +ul.main_menu {
6 6 border-radius: 4px;
7 7 margin: auto;
8 8 margin:30px 0;
... ... @@ -12,7 +12,7 @@ ul.main_menu {
12 12 position:relative;
13 13 overflow:hidden;
14 14 @include shade;
15   - .count {
  15 + .count {
16 16 position: relative;
17 17 top: -1px;
18 18 display: inline-block;
... ... @@ -29,12 +29,12 @@ ul.main_menu {
29 29 border-radius: 8px;
30 30 -moz-border-radius: 8px;
31 31 }
32   - .label {
  32 + .label {
33 33 background:$hover;
34 34 text-shadow:none;
35 35 color:$style_color;
36 36 }
37   - li {
  37 + li {
38 38 list-style-type: none;
39 39 margin: 0;
40 40 display: table-cell;
... ... @@ -43,7 +43,7 @@ ul.main_menu {
43 43 border-left: 1px solid #EEE;
44 44 border-bottom:2px solid #CFCFCF;
45 45  
46   - &:first-child{
  46 + &:first-child{
47 47 -webkit-border-top-left-radius: 4px;
48 48 -webkit-border-bottom-left-radius: 4px;
49 49 -moz-border-radius-topleft: 4px;
... ... @@ -53,31 +53,31 @@ ul.main_menu {
53 53 border-left: 0;
54 54 }
55 55  
56   - &.current {
  56 + &.current {
57 57 background-color:#D5D5D5;
58   - border-bottom: 2px solid $style_color;
  58 + border-bottom: 1px solid #AAA;
59 59 border-right: 1px solid #BBB;
60 60 border-left: 1px solid #BBB;
61 61 border-radius: 0 0 1px 1px;
62   - &:first-child{
  62 + &:first-child{
63 63 border-bottom:none;
64 64 border-left:none;
65 65 }
66 66 }
67 67  
68   - &.home {
69   - a {
  68 + &.home {
  69 + a {
70 70 background: url(home_icon.PNG) no-repeat center center;
71 71 text-indent:-9999px;
72 72 min-width:20px;
73   - img {
  73 + img {
74 74 position:relative;
75 75 top:4px;
76 76 }
77 77 }
78 78 }
79 79 }
80   - a {
  80 + a {
81 81 display: block;
82 82 text-align: center;
83 83 font-weight:bold;
... ...
app/assets/stylesheets/sections/projects.scss
... ... @@ -75,17 +75,21 @@
75 75 padding: 4px 7px;
76 76 border: 1px solid #CCC;
77 77 margin-bottom:5px;
78   - input[type=text] {
  78 +}
  79 +
  80 +.project_clone_holder {
  81 + input[type="text"] {
79 82 border: 1px solid #BBB;
  83 + box-shadow: none;
80 84 }
81 85 }
82 86  
83   -.save-project-loader {
84   - img {
  87 +.save-project-loader {
  88 + img {
85 89 margin-top:50px;
86 90 margin-bottom:50px;
87 91 }
88   - h3 {
  92 + h3 {
89 93 @extend .page_title;
90 94 }
91 95  
... ...
app/controllers/application_controller.rb
... ... @@ -120,22 +120,12 @@ class ApplicationController &lt; ActionController::Base
120 120 end
121 121 end
122 122  
123   - def load_refs
124   - if params[:ref].blank?
125   - @branch = params[:branch].blank? ? nil : params[:branch]
126   - @tag = params[:tag].blank? ? nil : params[:tag]
127   - @ref = @branch || @tag || @project.try(:default_branch) || Repository.default_ref
128   - else
129   - @ref = params[:ref]
130   - end
131   - end
132   -
133 123 def render_404
134 124 render file: File.join(Rails.root, "public", "404"), layout: false, status: "404"
135 125 end
136 126  
137 127 def require_non_empty_project
138   - redirect_to @project unless @project.repo_exists? && @project.has_commits?
  128 + redirect_to @project if @project.empty_repo?
139 129 end
140 130  
141 131 def no_cache_headers
... ...
app/controllers/commits_controller.rb
... ... @@ -59,12 +59,19 @@ class CommitsController &lt; ApplicationController
59 59  
60 60 def patch
61 61 @commit = project.commit(params[:id])
62   -
  62 +
63 63 send_data(
64 64 @commit.to_patch,
65 65 type: "text/plain",
66 66 disposition: 'attachment',
67   - filename: (@commit.id.to_s + ".patch")
  67 + filename: "#{@commit.id.patch}"
68 68 )
69 69 end
  70 +
  71 + protected
  72 +
  73 + def load_refs
  74 + @ref ||= params[:ref].presence || params[:branch].presence || params[:tag].presence
  75 + @ref ||= @ref || @project.try(:default_branch) || 'master'
  76 + end
70 77 end
... ...
app/controllers/projects_controller.rb
... ... @@ -50,7 +50,7 @@ class ProjectsController &lt; ApplicationController
50 50  
51 51 respond_to do |format|
52 52 format.html do
53   - if @project.repo_exists? && @project.has_commits?
  53 + unless @project.empty_repo?
54 54 @last_push = current_user.recent_push(@project.id)
55 55 render :show
56 56 else
... ...
app/helpers/gitlab_markdown_helper.rb
1 1 module GitlabMarkdownHelper
2   - # Replaces references (i.e. @abc, #123, !456, ...) in the text with links to
3   - # the appropriate items in Gitlab.
4   - #
5   - # text - the source text
6   - # html_options - extra options for the reference links as given to link_to
7   - #
8   - # note: reference links will only be generated if @project is set
9   - #
10   - # see Gitlab::Markdown for details on the supported syntax
11   - def gfm(text, html_options = {})
12   - return text if text.nil?
13   - return text if @project.nil?
14   -
15   - # Extract pre blocks so they are not altered
16   - # from http://github.github.com/github-flavored-markdown/
17   - extractions = {}
18   - text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) do |match|
19   - md5 = Digest::MD5.hexdigest(match)
20   - extractions[md5] = match
21   - "{gfm-extraction-#{md5}}"
22   - end
23   -
24   - # TODO: add popups with additional information
25   -
26   - parser = Gitlab::Markdown.new(@project, html_options)
27   - text = parser.parse(text)
28   -
29   - # Insert pre block extractions
30   - text.gsub!(/\{gfm-extraction-(\h{32})\}/) do
31   - extractions[$1]
32   - end
33   -
34   - sanitize text.html_safe, attributes: ActionView::Base.sanitized_allowed_attributes + %w(id class )
35   - end
  2 + include Gitlab::Markdown
36 3  
37 4 # Use this in places where you would normally use link_to(gfm(...), ...).
38 5 #
... ...
app/mailers/notify.rb
... ... @@ -111,18 +111,18 @@ class Notify &lt; ActionMailer::Base
111 111 # Examples
112 112 #
113 113 # >> subject('Lorem ipsum')
114   - # => "gitlab | Lorem ipsum"
  114 + # => "GitLab | Lorem ipsum"
115 115 #
116 116 # # Automatically inserts Project name when @project is set
117 117 # >> @project = Project.last
118 118 # => #<Project id: 1, name: "Ruby on Rails", path: "ruby_on_rails", ...>
119 119 # >> subject('Lorem ipsum')
120   - # => "gitlab | Lorem ipsum | Ruby on Rails"
  120 + # => "GitLab | Lorem ipsum | Ruby on Rails"
121 121 #
122 122 # # Accepts multiple arguments
123 123 # >> subject('Lorem ipsum', 'Dolor sit amet')
124   - # => "gitlab | Lorem ipsum | Dolor sit amet"
  124 + # => "GitLab | Lorem ipsum | Dolor sit amet"
125 125 def subject(*extra)
126   - "gitlab | " << extra.join(' | ') << (@project ? " | #{@project.name}" : "")
  126 + "GitLab | " << extra.join(' | ') << (@project ? " | #{@project.name}" : "")
127 127 end
128 128 end
... ...
app/models/note.rb
... ... @@ -103,7 +103,7 @@ class Note &lt; ActiveRecord::Base
103 103 # Returns true if this is an upvote note,
104 104 # otherwise false is returned
105 105 def upvote?
106   - note =~ /^\+1/ ? true : false
  106 + note.start_with?('+1') || note.start_with?(':+1:')
107 107 end
108 108 end
109 109 # == Schema Information
... ...
app/models/project.rb
... ... @@ -104,6 +104,8 @@ class Project &lt; ActiveRecord::Base
104 104 length: { within: 1..255 }
105 105  
106 106 validates :owner, presence: true
  107 + validates :issues_enabled, :wall_enabled, :merge_requests_enabled,
  108 + :wiki_enabled, inclusion: { in: [true, false] }
107 109 validate :check_limit
108 110 validate :repo_name
109 111  
... ... @@ -187,7 +189,7 @@ end
187 189 # private_flag :boolean(1) default(TRUE), not null
188 190 # code :string(255)
189 191 # owner_id :integer(4)
190   -# default_branch :string(255) default("master"), not null
  192 +# default_branch :string(255)
191 193 # issues_enabled :boolean(1) default(TRUE), not null
192 194 # wall_enabled :boolean(1) default(TRUE), not null
193 195 # merge_requests_enabled :boolean(1) default(TRUE), not null
... ...
app/models/users_project.rb
... ... @@ -14,7 +14,7 @@ class UsersProject &lt; ActiveRecord::Base
14 14 after_save :update_repository
15 15 after_destroy :update_repository
16 16  
17   - validates_uniqueness_of :user_id, scope: [:project_id]
  17 + validates_uniqueness_of :user_id, scope: [:project_id], message: "already exists in project"
18 18 validates_presence_of :user_id
19 19 validates_presence_of :project_id
20 20  
... ... @@ -48,10 +48,10 @@ class UsersProject &lt; ActiveRecord::Base
48 48  
49 49 def self.access_roles
50 50 {
51   - "Guest" => GUEST,
52   - "Reporter" => REPORTER,
  51 + "Guest" => GUEST,
  52 + "Reporter" => REPORTER,
53 53 "Developer" => DEVELOPER,
54   - "Master" => MASTER
  54 + "Master" => MASTER
55 55 }
56 56 end
57 57  
... ...
app/roles/account.rb
1   -module Account
  1 +module Account
  2 + # Returns a string for use as a Gitolite user identifier
  3 + #
  4 + # Note that Gitolite 2.x requires the following pattern for users:
  5 + #
  6 + # ^@?[0-9a-zA-Z][0-9a-zA-Z._\@+-]*$
2 7 def identifier
3   - email.gsub /[^[:alnum:]]/, "_"
  8 + # Replace non-word chars with underscores, then make sure it starts with
  9 + # valid chars
  10 + email.gsub(/\W/, '_').gsub(/\A([\W\_])+/, '')
4 11 end
5 12  
6 13 def is_admin?
... ...
app/roles/issue_commonality.rb
... ... @@ -16,7 +16,7 @@ module IssueCommonality
16 16 validates :title,
17 17 presence: true,
18 18 length: { within: 0..255 }
19   -
  19 + validates :closed, inclusion: { in: [true, false] }
20 20  
21 21 scope :opened, where(closed: false)
22 22 scope :closed, where(closed: true)
... ...
app/roles/push_observer.rb
  1 +# Includes methods for handling Git Push events
  2 +#
  3 +# Triggered by PostReceive job
1 4 module PushObserver
2 5 def observe_push(oldrev, newrev, ref, user)
3 6 data = post_receive_data(oldrev, newrev, ref, user)
... ... @@ -84,11 +87,10 @@ module PushObserver
84 87 data
85 88 end
86 89  
87   -
88   - # This method will be called after each post receive
89   - # and only if user present in gitlab.
90   - # All callbacks for post receive should be placed here
  90 + # This method will be called after each post receive and only if the provided
  91 + # user is present in GitLab.
91 92 #
  93 + # All callbacks for post receive should be placed here.
92 94 def trigger_post_receive(oldrev, newrev, ref, user)
93 95 # Create push event
94 96 self.observe_push(oldrev, newrev, ref, user)
... ... @@ -101,5 +103,11 @@ module PushObserver
101 103  
102 104 # Create satellite
103 105 self.satellite.create unless self.satellite.exists?
  106 +
  107 + # Discover the default branch, but only if it hasn't already been set to
  108 + # something else
  109 + if default_branch.nil?
  110 + update_attributes(default_branch: discover_default_branch)
  111 + end
104 112 end
105 113 end
... ...
app/roles/repository.rb
... ... @@ -8,6 +8,10 @@ module Repository
8 8 false
9 9 end
10 10  
  11 + def empty_repo?
  12 + !repo_exists? || !has_commits?
  13 + end
  14 +
11 15 def commit(commit_id = nil)
12 16 Commit.find_or_first(repo, commit_id, root_ref)
13 17 end
... ... @@ -38,7 +42,7 @@ module Repository
38 42  
39 43 def has_post_receive_file?
40 44 hook_file = File.join(path_to_repo, 'hooks', 'post-receive')
41   - File.exists?(hook_file)
  45 + File.exists?(hook_file)
42 46 end
43 47  
44 48 def tags
... ... @@ -67,7 +71,7 @@ module Repository
67 71  
68 72 def repo_exists?
69 73 @repo_exists ||= (repo && !repo.branches.empty?)
70   - rescue
  74 + rescue
71 75 @repo_exists = false
72 76 end
73 77  
... ... @@ -90,24 +94,42 @@ module Repository
90 94 end.sort_by(&:name)
91 95 end
92 96  
  97 + # Discovers the default branch based on the repository's available branches
  98 + #
  99 + # - If no branches are present, returns nil
  100 + # - If one branch is present, returns its name
  101 + # - If two or more branches are present, returns the one that has a name
  102 + # matching root_ref (default_branch or 'master' if default_branch is nil)
  103 + def discover_default_branch
  104 + branches = heads.collect(&:name)
  105 +
  106 + if branches.length == 0
  107 + nil
  108 + elsif branches.length == 1
  109 + branches.first
  110 + else
  111 + branches.select { |v| v == root_ref }.first
  112 + end
  113 + end
  114 +
93 115 def has_commits?
94 116 !!commit
95 117 end
96 118  
97   - def root_ref
  119 + def root_ref
98 120 default_branch || "master"
99 121 end
100 122  
101   - def root_ref? branch
  123 + def root_ref?(branch)
102 124 root_ref == branch
103 125 end
104 126  
105 127 # Archive Project to .tar.gz
106 128 #
107   - # Already packed repo archives stored at
  129 + # Already packed repo archives stored at
108 130 # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
109 131 #
110   - def archive_repo ref
  132 + def archive_repo(ref)
111 133 ref = ref || self.root_ref
112 134 commit = self.commit(ref)
113 135 return nil unless commit
... ... @@ -134,6 +156,6 @@ module Repository
134 156 end
135 157  
136 158 def http_url_to_repo
137   - http_url = [Gitlab.config.url, "/", path, ".git"].join()
  159 + http_url = [Gitlab.config.url, "/", path, ".git"].join('')
138 160 end
139 161 end
... ...
app/views/deploy_keys/_form.html.haml
... ... @@ -11,8 +11,13 @@
11 11 .input= f.text_field :title
12 12 .clearfix
13 13 = f.label :key
14   - .input= f.text_area :key, class: "xlarge"
  14 + .input
  15 + = f.text_area :key, class: [:xxlarge, :thin_area]
  16 + %p.hint
  17 + Paste a machine public key here. Read more about how generate it
  18 + = link_to "here", help_ssh_path
  19 +
15 20 .actions
16   - = f.submit 'Save', class: "primary btn"
17   - = link_to "Cancel", project_deploy_keys_path(@project), class: "btn"
  21 + = f.submit 'Save', class: "save-btn btn"
  22 + = link_to "Cancel", project_deploy_keys_path(@project), class: "btn cancel-btn"
18 23  
... ...
app/views/deploy_keys/index.html.haml
1 1 = render "repositories/head"
2   -- if can? current_user, :admin_project, @project
3   - .alert-message.block-message
4   - Deploy keys allow read-only access to repository.
  2 +
  3 +%p.slead
  4 + Deploy keys allow read-only access to repository. It matches perfectly for CI, staging or production servers.
  5 +
  6 + - if can? current_user, :admin_project, @project
5 7 = link_to new_project_deploy_key_path(@project), class: "btn small", title: "New Deploy Key" do
6 8 Add Deploy Key
7   -
8 9 - if @keys.any?
9 10 %table
  11 + %thead
  12 + %tr
  13 + %th Keys
  14 + %th
  15 + %th
10 16 - @keys.each do |key|
11 17 = render(partial: 'show', locals: {key: key})
... ...
app/views/deploy_keys/new.html.haml
1 1 = render "repositories/head"
2 2  
3   -%h3 New Deploy key
  3 +%h3.page_title New Deploy key
4 4 %hr
5 5  
6 6 = render 'form'
... ...
app/views/deploy_keys/show.html.haml
1 1 = render "repositories/head"
2   -%h3= @key.title
  2 +%h3.page_title
  3 + Deploy key:
  4 + = @key.title
  5 + %small
  6 + created at
  7 + = @key.created_at.stamp("Aug 21, 2011")
  8 +.back_link
  9 + = link_to project_deploy_keys_path(@project) do
  10 + &larr; To keys list
3 11 %hr
4 12 %pre= @key.key
5   -.actions
  13 +.right
6 14 = link_to 'Remove', project_deploy_key_path(@key.project, @key), confirm: 'Are you sure?', method: :delete, class: "danger btn delete-key"
7   - .clear
... ...
app/views/errors/gitolite.html.haml
1 1 %h1 Git Error
2 2 %hr
3   -%h2 Gitlab was unable to access your Gitolite system.
  3 +%h2 GitLab was unable to access your Gitolite system.
4 4  
5 5 .git_error_tips
6 6 %h4 Tips for Administrator:
... ...
app/views/help/api.html.haml
... ... @@ -15,6 +15,8 @@
15 15 %a{href: "#users"} Users
16 16 %li
17 17 %a{href: "#issues"} Issues
  18 + %li
  19 + %a{href: "#milestones"} Milestones
18 20  
19 21 .file_holder#README
20 22 .file_title
... ...
app/views/help/index.html.haml
... ... @@ -30,7 +30,7 @@
30 30 %h5= link_to "API", help_api_path
31 31  
32 32 %li
33   - %h5= link_to "Gitlab Markdown", help_markdown_path
  33 + %h5= link_to "GitLab Markdown", help_markdown_path
34 34  
35 35 %li
36 36 %h5= link_to "SSH keys", help_ssh_path
... ...
app/views/help/markdown.html.haml
1   -%h3.page_title Gitlab Flavored Markdown
  1 +%h3.page_title GitLab Flavored Markdown
2 2 .back_link
3 3 = link_to help_path do
4 4 &larr; to index
... ... @@ -7,7 +7,7 @@
7 7 .row
8 8 .span8
9 9 %p
10   - For Gitlab we developed something we call "Gitlab Flavored Markdown" (GFM).
  10 + For GitLab we developed something we call "GitLab Flavored Markdown" (GFM).
11 11 It extends the standard Markdown in a few significant ways adds some useful functionality.
12 12  
13 13 %p You can use GFM in:
... ... @@ -62,7 +62,7 @@
62 62 %p becomes
63 63 = markdown %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```}
64 64  
65   - %h4 Special Gitlab references
  65 + %h4 Special GitLab references
66 66  
67 67 %p
68 68 GFM recognizes special references.
... ... @@ -90,12 +90,11 @@
90 90 -# this example will only be shown if the user has a project with at least one issue
91 91 - if @project = current_user.projects.first
92 92 - if issue = @project.issues.first
93   - %p For example in your #{link_to @project.name, project_path(@project)} project something like
  93 + %p For example in your #{link_to @project.name, project_path(@project)} project, writing:
94 94 %pre= "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
95   - %p becomes
96   - = markdown "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
97   -
98   -
  95 + %p becomes:
  96 + %pre= gfm "This is related to ##{issue.id}. @#{current_user.name} is working on solving it."
  97 + - @project = nil # Prevent this from bubbling up to page title
99 98  
100 99 .span4.right
101 100 .alert.alert-info
... ...
app/views/help/ssh.html.haml
... ... @@ -5,7 +5,7 @@
5 5 %hr
6 6  
7 7 %p.slead
8   - SSH key allows you to establish a secure connection between your computer and Gitlab
  8 + SSH key allows you to establish a secure connection between your computer and GitLab
9 9  
10 10 %p.slead
11 11 To generate a new SSH key just open your terminal and use code below.
... ... @@ -17,7 +17,7 @@
17 17 \# Generating public/private rsa key pair...
18 18  
19 19 %p.slead
20   - Next just use code below to dump your public key and add to GITLAB SSH Keys
  20 + Next just use code below to dump your public key and add to GitLab SSH Keys
21 21  
22 22 %pre.dark
23 23 cat ~/.ssh/id_rsa.pub
... ...
app/views/help/system_hooks.html.haml
... ... @@ -5,7 +5,7 @@
5 5 %hr
6 6  
7 7 %p.slead
8   - Your Gitlab instance can perform HTTP POST request on next event: create_project, delete_project, create_user, delete_user, change_team_member.
  8 + Your GitLab instance can perform HTTP POST request on next event: create_project, delete_project, create_user, delete_user, change_team_member.
9 9 %br
10 10 System Hooks can be used for logging or change information in LDAP server.
11 11 %br
... ...
app/views/help/web_hooks.html.haml
... ... @@ -5,11 +5,11 @@
5 5 %hr
6 6  
7 7 %p.slead
8   - Every Gitlab project can trigger a web server whenever the repo is pushed to.
  8 + Every GitLab project can trigger a web server whenever the repo is pushed to.
9 9 %br
10 10 Web Hooks can be used to update an external issue tracker, trigger CI builds, update a backup mirror, or even deploy to your production server.
11 11 %br
12   - GITLAB will send POST request with commits information on every push.
  12 + GitLab will send POST request with commits information on every push.
13 13 %h5 Hooks request example:
14 14 = render "hooks/data_ex"
15 15  
... ...
app/views/help/workflow.html.haml
... ... @@ -24,7 +24,7 @@
24 24 git commit -am "My feature is ready"
25 25  
26 26 %li
27   - %p Push your branch to gitlabhq
  27 + %p Push your branch to GitLab
28 28 .bash
29 29 %pre.dark
30 30 git push origin $feature_name
... ...
app/views/hooks/_data_ex.html.erb
... ... @@ -32,7 +32,7 @@
32 32 :timestamp => "2012-01-03T23:36:29+02:00",
33 33 :url => "http://localhost/diaspora/commits/da1560886d...",
34 34 :author => {
35   - :name => "gitlab dev user",
  35 + :name => "GitLab dev user",
36 36 :email => "gitlabdev@dv6700.(none)"
37 37 }
38 38 }
... ...
app/views/issues/_form.html.haml
... ... @@ -38,7 +38,7 @@
38 38 = f.label :description, "Details"
39 39 .input
40 40 = f.text_area :description, maxlength: 2000, class: "xxlarge", rows: 14
41   - %p.hint Issues are parsed with #{link_to "Gitlab Flavored Markdown", help_markdown_path, target: '_blank'}.
  41 + %p.hint Issues are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
42 42  
43 43  
44 44 .actions
... ...
app/views/keys/index.html.haml
... ... @@ -4,7 +4,7 @@
4 4  
5 5 %hr
6 6 %p.slead
7   - SSH key allows you to establish a secure connection between your computer and Gitlab
  7 + SSH key allows you to establish a secure connection between your computer and GitLab
8 8  
9 9  
10 10 %table#keys-table
... ...
app/views/keys/show.html.haml
... ... @@ -10,5 +10,5 @@
10 10 %hr
11 11  
12 12 %pre= @key.key
13   -.actions
  13 +.right
14 14 = link_to 'Remove', @key, confirm: 'Are you sure?', method: :delete, class: "btn danger delete-key"
... ...
app/views/layouts/notify.html.haml
... ... @@ -2,7 +2,7 @@
2 2 %head
3 3 %meta{content: "text/html; charset=utf-8", "http-equiv" => "Content-Type"}
4 4 %title
5   - gitlabhq
  5 + GitLab
6 6 :css
7 7 .header h1 {color: #BBBBBB !important; font: bold 32px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 40px;}
8 8 .header p {color: #c6c6c6; font: normal 12px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 18px;}
... ... @@ -21,7 +21,7 @@
21 21
22 22 %td{align: "left", style: "padding: 18px 0 10px;", width: "580"}
23 23 %h1{style: "color: #BBBBBB; font: normal 32px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 40px;"}
24   - gitlab
  24 + GITLAB
25 25 - if @project
26 26 | #{@project.name}
27 27 %table{align: "center", bgcolor: "#fff", border: "0", cellpadding: "0", cellspacing: "0", style: "font-family: Helvetica, Arial, sans-serif; background: #fff;", width: "600"}
... ...
app/views/milestones/_form.html.haml
... ... @@ -22,7 +22,7 @@
22 22 = f.label :description, "Description", class: "control-label"
23 23 .controls
24 24 = f.text_area :description, maxlength: 2000, class: "input-xlarge", rows: 10
25   - %p.hint Milestones are parsed with #{link_to "Gitlab Flavored Markdown", help_markdown_path, target: '_blank'}.
  25 + %p.hint Milestones are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
26 26 .span6
27 27 .control-group
28 28 = f.label :due_date, "Due Date", class: "control-label"
... ...
app/views/notes/_form.html.haml
... ... @@ -11,7 +11,7 @@
11 11 = f.text_area :note, size: 255, class: 'note-text'
12 12 #preview-note.preview_note.hide
13 13 .hint
14   - .right Comments are parsed with #{link_to "Gitlab Flavored Markdown", help_markdown_path, target: '_blank'}.
  14 + .right Comments are parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
15 15 .clearfix
16 16  
17 17 .row.note_advanced_opts.hide
... ...
app/views/notify/new_user_email.html.haml
... ... @@ -6,7 +6,7 @@
6 6 %h2{style: "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "}
7 7 Hi #{@user['name']}!
8 8 %p{style: "color:#767676; font-weight: normal; margin: 0; padding: 0; line-height: 20px; font-size: 12px;font-family: Helvetica, Arial, sans-serif; "}
9   - Administrator created account for you. Now you are a member of company gitlab application.
  9 + Administrator created account for you. Now you are a member of company GitLab application.
10 10 %td{style: "font-size: 1px; line-height: 1px;", width: "21"}
11 11 %tr
12 12 %td{style: "font-size: 1px; line-height: 1px;", width: "21"}
... ...
app/views/projects/_clone_panel.html.haml
... ... @@ -3,19 +3,19 @@
3 3 .span7
4 4 .form-horizontal
5 5 .input-prepend.project_clone_holder
6   - = link_to "SSH", "#", class: "btn small active", :"data-clone" => @project.ssh_url_to_repo
7   - = link_to "HTTP", "#", class: "btn small", :"data-clone" => @project.http_url_to_repo
  6 + %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH
  7 + %button{class: "btn small", :"data-clone" => @project.http_url_to_repo} HTTP
8 8 = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5"
9 9 .span4.right
10 10 .right
11   - - if can? current_user, :download_code, @project
12   - = link_to archive_project_repository_path(@project), class: "btn small grouped" do
13   - %i.icon-download-alt
14   - Download
15   - - if @project.merge_requests_enabled && can?(current_user, :write_merge_request, @project)
16   - = link_to new_project_merge_request_path(@project), title: "New Merge Request", class: "btn small grouped" do
17   - Merge Request
18   - - if @project.issues_enabled && can?(current_user, :write_issue, @project)
19   - = link_to new_project_issue_path(@project), title: "New Issue", class: "btn small grouped" do
20   - Issue
21   -
  11 + - unless @project.empty_repo?
  12 + - if can? current_user, :download_code, @project
  13 + = link_to archive_project_repository_path(@project), class: "btn small grouped" do
  14 + %i.icon-download-alt
  15 + Download
  16 + - if @project.merge_requests_enabled && can?(current_user, :write_merge_request, @project)
  17 + = link_to new_project_merge_request_path(@project), title: "New Merge Request", class: "btn small grouped" do
  18 + Merge Request
  19 + - if @project.issues_enabled && can?(current_user, :write_issue, @project)
  20 + = link_to new_project_issue_path(@project), title: "New Issue", class: "btn small grouped" do
  21 + Issue
... ...
app/views/projects/_show.html.haml
... ... @@ -1,23 +0,0 @@
1   -%h5.title
2   - = @project.name
3   -%br
4   -%div
5   - %a.btn.info{href: tree_project_ref_path(@project, @project.root_ref)} Browse code
6   - &nbsp;
7   - %a.btn{href: project_commits_path(@project)} Commits
8   - %strong.right
9   - = link_to project_path(@project) do
10   - Switch to project &rarr;
11   -%br
12   -.alert-message.block-message.warning
13   - .input
14   - .input-prepend
15   - %span.add-on git clone
16   - = text_field_tag :project_clone, @project.url_to_repo, class: "xlarge one_click_select git_clone_url"
17   -
18   -= simple_format @project.description
19   -- unless @events.blank?
20   - %h4.middle_title Recent Activity
21   - .content_list= render @events
22   -
23   -
app/views/projects/empty.html.haml
1 1 = render 'shared/no_ssh'
2   -.project_clone_panel
3   - .row
4   - .span7
5   - .form-horizontal
6   - .input-prepend.project_clone_holder
7   - = link_to "SSH", "#", class: "btn small active", :"data-clone" => @project.ssh_url_to_repo
8   - = link_to "HTTP", "#", class: "btn small", :"data-clone" => @project.http_url_to_repo
9   - = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5"
  2 += render 'clone_panel'
  3 +
10 4 %div.git-empty
11 5 %h4 Git global setup:
12 6 %pre.dark
... ... @@ -36,16 +30,3 @@
36 30 - if can? current_user, :admin_project, @project
37 31 .prepend-top-20
38 32 = link_to 'Remove project', @project, confirm: 'Are you sure?', method: :delete, class: "btn danger right"
39   -
40   -
41   -
42   -:javascript
43   - $(function(){
44   - var link_sel = ".project_clone_holder a";
45   - $(link_sel).bind("click", function() {
46   - $(link_sel).removeClass("active");
47   - $(this).addClass("active");
48   - $("#project_clone").val($(this).attr("data-clone"));
49   - })
50   - })
51   -
... ...
app/views/projects/show.html.haml
... ... @@ -2,13 +2,3 @@
2 2 = render 'clone_panel'
3 3 = render "events/event_last_push", event: @last_push
4 4 .content_list= render @events
5   -
6   -:javascript
7   - $(function(){
8   - var link_sel = ".project_clone_holder a";
9   - $(link_sel).bind("click", function() {
10   - $(link_sel).removeClass("active");
11   - $(this).addClass("active");
12   - $("#project_clone").val($(this).attr("data-clone"));
13   - })
14   - })
... ...
app/views/refs/_head.html.haml
... ... @@ -7,4 +7,8 @@
7 7 %li{class: "#{'active' if (controller.controller_name == "refs") }"}
8 8 = link_to tree_project_ref_path(@project, @ref) do
9 9 Source
10   -
  10 + %li.right
  11 + .input-prepend.project_clone_holder
  12 + %button{class: "btn small active", :"data-clone" => @project.ssh_url_to_repo} SSH
  13 + %button{class: "btn small", :"data-clone" => @project.http_url_to_repo} HTTP
  14 + = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5"
... ...
app/views/refs/tree.js.haml
... ... @@ -6,5 +6,5 @@
6 6  
7 7 // Load last commit log for each file in tree
8 8 $('#tree-slider').waitForImages(function() {
9   - ajaxGet('#{@logs_path}');
  9 + ajaxGet('#{@logs_path}');
10 10 });
... ...
app/views/team_members/show.html.haml
... ... @@ -3,7 +3,7 @@
3 3  
4 4 .team_member_show
5 5 - if can? current_user, :admin_project, @project
6   - = link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "right btn btn-danger"
  6 + = link_to 'Remove from team', project_team_member_path(project_id: @project, id: @team_member.id), confirm: 'Are you sure?', method: :delete, class: "right btn danger"
7 7 .profile_avatar_holder
8 8 = image_tag gravatar_icon(user.email, 60), class: "borders"
9 9 %h3
... ...
app/views/wikis/_form.html.haml
... ... @@ -14,7 +14,7 @@
14 14 .middle_box_content
15 15 .input
16 16 %span.cgray
17   - Wiki content is parsed with #{link_to "Gitlab Flavored Markdown", help_markdown_path, target: '_blank'}.
  17 + Wiki content is parsed with #{link_to "GitLab Flavored Markdown", help_markdown_path, target: '_blank'}.
18 18 To link to a (new) page you can just type
19 19 %code [Link Title](page-slug)
20 20 \.
... ...
config/routes.rb
... ... @@ -50,10 +50,6 @@ Gitlab::Application.routes.draw do
50 50 end
51 51 end
52 52 resources :team_members, :only => [:edit, :update, :destroy]
53   - get 'mailer/preview_note'
54   - get 'mailer/preview_user_new'
55   - get 'mailer/preview_issue_new'
56   -
57 53 resources :hooks, :only => [:index, :create, :destroy] do
58 54 get :test
59 55 end
... ...
db/migrate/20120905043334_set_default_branch_default_to_nil.rb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +class SetDefaultBranchDefaultToNil < ActiveRecord::Migration
  2 + def up
  3 + # Set the default_branch to allow nil, and default it to nil
  4 + change_column_null(:projects, :default_branch, true)
  5 + change_column_default(:projects, :default_branch, nil)
  6 + end
  7 +
  8 + def down
  9 + change_column_null(:projects, :default_branch, false)
  10 + change_column_default(:projects, :default_branch, 'master')
  11 + end
  12 +end
... ...
db/schema.rb
... ... @@ -11,7 +11,7 @@
11 11 #
12 12 # It's strongly recommended to check this file into your version control system.
13 13  
14   -ActiveRecord::Schema.define(:version => 20120729131232) do
  14 +ActiveRecord::Schema.define(:version => 20120905043334) do
15 15  
16 16 create_table "events", :force => true do |t|
17 17 t.string "target_type"
... ... @@ -98,16 +98,16 @@ ActiveRecord::Schema.define(:version =&gt; 20120729131232) do
98 98 t.string "name"
99 99 t.string "path"
100 100 t.text "description"
101   - t.datetime "created_at", :null => false
102   - t.datetime "updated_at", :null => false
103   - t.boolean "private_flag", :default => true, :null => false
  101 + t.datetime "created_at", :null => false
  102 + t.datetime "updated_at", :null => false
  103 + t.boolean "private_flag", :default => true, :null => false
104 104 t.string "code"
105 105 t.integer "owner_id"
106   - t.string "default_branch", :default => "master", :null => false
107   - t.boolean "issues_enabled", :default => true, :null => false
108   - t.boolean "wall_enabled", :default => true, :null => false
109   - t.boolean "merge_requests_enabled", :default => true, :null => false
110   - t.boolean "wiki_enabled", :default => true, :null => false
  106 + t.string "default_branch"
  107 + t.boolean "issues_enabled", :default => true, :null => false
  108 + t.boolean "wall_enabled", :default => true, :null => false
  109 + t.boolean "merge_requests_enabled", :default => true, :null => false
  110 + t.boolean "wiki_enabled", :default => true, :null => false
111 111 end
112 112  
113 113 create_table "protected_branches", :force => true do |t|
... ...
doc/api/README.md
1   -# Gitlab API
  1 +# GitLab API
2 2  
3   -All API requests require authentication. You need to pass `private_token` parameter to authenticate.
  3 +All API requests require authentication. You need to pass a `private_token` parameter to authenticate. You can find or reset your private token in your profile.
4 4  
5   -To get or reset your token visit your profile.
6   -
7   -If no or invalid `private_token` provided error message will be returned with status code 401:
  5 +If no, or an invalid, `private_token` is provided then an error message will be returned with status code 401:
8 6  
9 7 ```json
10 8 {
... ... @@ -12,10 +10,9 @@ If no or invalid `private_token` provided error message will be returned with st
12 10 }
13 11 ```
14 12  
15   -API requests should be prefixed with `api` and the API version.
16   -API version is equal to Gitlab major version number and defined in `lib/api.rb`.
  13 +API requests should be prefixed with `api` and the API version. The API version is equal to the GitLab major version number, which is defined in `lib/api.rb`.
17 14  
18   -Example of valid API request:
  15 +Example of a valid API request:
19 16  
20 17 ```
21 18 GET http://example.com/api/v2/projects?private_token=QVy1PB7sTxfy4pqfZM1U
... ...
doc/api/projects.md
1 1 ## List projects
2 2  
3   -Get a list of authenticated user's projects.
  3 +Get a list of projects owned by the authenticated user.
4 4  
5 5 ```
6 6 GET /projects
... ... @@ -55,7 +55,7 @@ GET /projects
55 55  
56 56 ## Single project
57 57  
58   -Get an authenticated user's project.
  58 +Get a specific project, identified by project ID, which is owned by the authentication user.
59 59  
60 60 ```
61 61 GET /projects/:id
... ... @@ -102,6 +102,12 @@ Parameters:
102 102 + `name` (required) - new project name
103 103 + `code` (optional) - new project code, uses project name if not set
104 104 + `path` (optional) - new project path, uses project name if not set
  105 ++ `description (optional) - short project description
  106 ++ `default_branch` (optional) - 'master' by default
  107 ++ `issues_enabled` (optional) - enabled by default
  108 ++ `wall_enabled` (optional) - enabled by default
  109 ++ `merge_requests_enabled` (optional) - enabled by default
  110 ++ `wiki_enabled` (optional) - enabled by default
105 111  
106 112 Will return created project with status `201 Created` on success, or `404 Not
107 113 found` on fail.
... ... @@ -109,7 +115,7 @@ found` on fail.
109 115  
110 116 ## Project repository branches
111 117  
112   -Get a list of project repository branches sorted by name alphabetically.
  118 +Get a list of repository branches from a project, sorted by name alphabetically.
113 119  
114 120 ```
115 121 GET /projects/:id/repository/branches
... ... @@ -186,7 +192,7 @@ Parameters:
186 192  
187 193 ## Project repository tags
188 194  
189   -Get a list of project repository tags sorted by name in reverse alphabetical order.
  195 +Get a list of repository tags from a project, sorted by name in reverse alphabetical order.
190 196  
191 197 ```
192 198 GET /projects/:id/repository/tags
... ... @@ -237,3 +243,4 @@ Parameters:
237 243 + `filepath` (required) - The path the file
238 244  
239 245 Will return the raw file contents.
  246 +
... ...
doc/debian_ubuntu.sh
... ... @@ -1,45 +0,0 @@
1   -#!/bin/sh
2   -
3   -sudo apt-get update
4   -sudo apt-get upgrade
5   -
6   -sudo DEBIAN_FRONTEND='noninteractive' apt-get install -y postfix-policyd-spf-python # Install postfix without prompting.
7   -sudo apt-get install -y git git-core wget curl gcc checkinstall libxml2-dev libxslt-dev sqlite3 libsqlite3-dev libcurl4-openssl-dev libreadline-gplv2-dev libc6-dev libssl-dev libmysql++-dev make build-essential zlib1g-dev libicu-dev redis-server openssh-server python-dev python-pip libyaml-dev
8   -
9   -wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p194.tar.gz
10   -tar xfvz ruby-1.9.3-p194.tar.gz
11   -cd ruby-1.9.3-p194
12   -./configure
13   -make
14   -sudo make install
15   -
16   -sudo adduser \
17   - --system \
18   - --shell /bin/sh \
19   - --gecos 'git version control' \
20   - --group \
21   - --disabled-password \
22   - --home /home/git \
23   - git
24   -
25   -sudo adduser --disabled-login --gecos 'gitlab system' gitlab
26   -
27   -sudo usermod -a -G git gitlab
28   -
29   -sudo -H -u gitlab ssh-keygen -q -N '' -t rsa -f /home/gitlab/.ssh/id_rsa
30   -
31   -cd /home/git
32   -sudo -H -u git git clone git://github.com/gitlabhq/gitolite /home/git/gitolite
33   -
34   -sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; /home/git/gitolite/src/gl-system-install"
35   -sudo cp /home/gitlab/.ssh/id_rsa.pub /home/git/gitlab.pub
36   -sudo chmod 777 /home/git/gitlab.pub
37   -
38   -sudo -u git -H sed -i 's/0077/0007/g' /home/git/share/gitolite/conf/example.gitolite.rc
39   -sudo -u git -H sh -c "PATH=/home/git/bin:$PATH; gl-setup -q /home/git/gitlab.pub"
40   -
41   -sudo chmod -R g+rwX /home/git/repositories/
42   -sudo chown -R git:git /home/git/repositories/
43   -
44   -sudo -u gitlab -H git clone git@localhost:gitolite-admin.git /tmp/gitolite-admin
45   -sudo rm -rf /tmp/gitolite-admin
doc/installation.md
... ... @@ -20,7 +20,7 @@ You might have some luck using these, but no guarantees:
20 20 - MacOS X
21 21 - FreeBSD
22 22  
23   -Gitlab does **not** run on Windows and we have no plans of making Gitlab compatible.
  23 +GitLab does **not** run on Windows and we have no plans of making GitLab compatible.
24 24  
25 25 ## This installation guide created for Debian/Ubuntu and properly tested.
26 26  
... ... @@ -28,40 +28,44 @@ The installation consists of 6 steps:
28 28  
29 29 1. Install packages / dependencies
30 30 2. Install ruby
31   -3. Install gitolite
32   -4. Install and configure Gitlab.
  31 +3. Install Gitolite
  32 +4. Install and configure GitLab.
33 33 5. Start the web front-end
34 34 6. Start a Resque worker (for background processing)
35 35  
36 36 ### IMPORTANT
37 37  
38   -Please make sure you have followed all the steps below before posting to the mailinglist with installation and configuration questions.
  38 +Please make sure you have followed all the steps below before posting to the mailing list with installation and configuration questions.
39 39  
40   -Only create a Github Issue if you want a specific part of this installation guide updated.
  40 +Only create a GitHub Issue if you want a specific part of this installation guide updated.
41 41  
42 42 Also read the [Read this before you submit an issue](https://github.com/gitlabhq/gitlabhq/wiki/Read-this-before-you-submit-an-issue) wiki page.
43 43  
44 44 > - - -
45   -> First 3 steps can be easily skipped with simply install script:
  45 +> The first 3 steps of this guide can be easily skipped by executing an install script:
46 46 >
47 47 > # Install curl and sudo
48 48 > apt-get install curl sudo
49 49 >
50 50 > # 3 steps in 1 command :)
51   -> curl https://raw.github.com/gitlabhq/gitlabhq/master/doc/debian_ubuntu.sh | sh
  51 +> curl https://raw.github.com/gitlabhq/gitlab-recipes/master/install/debian_ubuntu.sh | sh
52 52 >
53   -> Now you can go to step 4"
  53 +> Now you can go to [Step 4](#4-install-gitlab-and-configuration-check-status-configuration)
54 54 >
55   -> Or if you are installing on Amazon Web Services using Ubuntu 12.04 you can do all steps (1 to 6) at once with:
  55 +> Or if you are installing on Amazon Web Services using Ubuntu 12.04 you can do all steps (1 to 6) at once with:
56 56 >
57   -> curl https://raw.github.com/gitlabhq/gitlabhq/master/lib/support/aws/debian_ubuntu_aws.sh | sh
  57 +> curl https://raw.github.com/gitlabhq/gitlab-recipes/master/install/debian_ubuntu_aws.sh | sh
58 58 >
59   -> for more detailed instructions read the HOWTO section of [the script](https://github.com/gitlabhq/gitlabhq/blob/master/lib/support/aws/debian_ubuntu_aws.sh)
  59 +> for more detailed instructions read the HOWTO section of [the script](https://github.com/gitlabhq/gitlab-recipes/blob/master/install/debian_ubuntu_aws.sh)
60 60 > - - -
61 61  
62 62 # 1. Install packages
63 63  
64   -*Keep in mind that `sudo` is not installed for debian by default. You should install it with as root:* **apt-get update && apt-get upgrade && apt-get install sudo**
  64 +*Keep in mind that `sudo` is not installed on Debian by default. You should install it as root:*
  65 +
  66 + apt-get update && apt-get upgrade && apt-get install sudo
  67 +
  68 +Now install the required packages:
65 69  
66 70 sudo apt-get update
67 71 sudo apt-get upgrade
... ... @@ -71,16 +75,16 @@ Also read the [Read this before you submit an issue](https://github.com/gitlabhq
71 75 # If you want to use MySQL:
72 76 sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev
73 77  
74   -# 2. Install ruby
  78 +# 2. Install Ruby
75 79  
76   - wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.2-p290.tar.gz
77   - tar xzfv ruby-1.9.2-p290.tar.gz
78   - cd ruby-1.9.2-p290
  80 + wget http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.3-p194.tar.gz
  81 + tar xfvz ruby-1.9.3-p194.tar.gz
  82 + cd ruby-1.9.3-p194
79 83 ./configure
80 84 make
81 85 sudo make install
82 86  
83   -# 3. Install gitolite
  87 +# 3. Install Gitolite
84 88  
85 89 Create user for git:
86 90  
... ... @@ -93,12 +97,12 @@ Create user for git:
93 97 --home /home/git \
94 98 git
95 99  
96   -Create user for gitlab:
  100 +Create user for GitLab:
97 101  
98 102 # ubuntu/debian
99 103 sudo adduser --disabled-login --gecos 'gitlab system' gitlab
100 104  
101   -Add your user to git group:
  105 +Add your user to the `git` group:
102 106  
103 107 sudo usermod -a -G git gitlab
104 108  
... ... @@ -106,10 +110,10 @@ Generate key:
106 110  
107 111 sudo -H -u gitlab ssh-keygen -q -N '' -t rsa -f /home/gitlab/.ssh/id_rsa
108 112  
109   -Get gitolite source code:
  113 +Clone GitLab's fork of the Gitolite source code:
110 114  
111 115 cd /home/git
112   - sudo -H -u git git clone git://github.com/gitlabhq/gitolite /home/git/gitolite
  116 + sudo -H -u git git clone https://github.com/gitlabhq/gitolite.git /home/git/gitolite
113 117  
114 118 Setup:
115 119  
... ... @@ -135,23 +139,23 @@ Permissions:
135 139 # if succeed you can remove it
136 140 sudo rm -rf /tmp/gitolite-admin
137 141  
138   -**IMPORTANT! If you cant clone `gitolite-admin` repository - DONT PROCEED INSTALLATION**
  142 +**IMPORTANT! If you can't clone `gitolite-admin` repository - DO NOT PROCEED WITH INSTALLATION**
  143 +Check the [Trouble Shooting Guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide)
  144 +and ensure you have followed all of the above steps carefully.
139 145  
140   -# 4. Install gitlab and configuration. Check status configuration.
  146 +# 4. Clone GitLab source and install prerequisites
141 147  
142 148 sudo gem install charlock_holmes --version '0.6.8'
143 149 sudo pip install pygments
144 150 sudo gem install bundler
145 151 cd /home/gitlab
146   - sudo -H -u gitlab git clone -b stable git://github.com/gitlabhq/gitlabhq.git gitlab
  152 + sudo -H -u gitlab git clone -b stable https://github.com/gitlabhq/gitlabhq.git gitlab
147 153 cd gitlab
148 154  
149   - sudo -u gitlab mkdir tmp
150   -
151 155 # Rename config files
152 156 sudo -u gitlab cp config/gitlab.yml.example config/gitlab.yml
153 157  
154   -#### Select db you want to use
  158 +#### Select the database you want to use
155 159  
156 160 # SQLite
157 161 sudo -u gitlab cp config/database.yml.sqlite config/database.yml
... ... @@ -163,7 +167,7 @@ Permissions:
163 167 # Login to MySQL
164 168 $ mysql -u root -p
165 169  
166   - # Create the gitlabhq production database
  170 + # Create the GitLab production database
167 171 mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
168 172  
169 173 # Create the MySQL User change $password to a real password
... ... @@ -179,15 +183,17 @@ Permissions:
179 183  
180 184 sudo -u gitlab -H bundle install --without development test --deployment
181 185  
182   -#### Setup DB
  186 +#### Setup database
183 187  
184 188 sudo -u gitlab bundle exec rake gitlab:app:setup RAILS_ENV=production
185 189  
186   -#### Setup gitlab hooks
  190 +#### Setup GitLab hooks
187 191  
188 192 sudo cp ./lib/hooks/post-receive /home/git/share/gitolite/hooks/common/post-receive
189 193 sudo chown git:git /home/git/share/gitolite/hooks/common/post-receive
190 194  
  195 +#### Check application status
  196 +
191 197 Checking status:
192 198  
193 199 sudo -u gitlab bundle exec rake gitlab:app:status RAILS_ENV=production
... ... @@ -208,9 +214,9 @@ Checking status:
208 214 UMASK for .gitolite.rc is 0007? ............YES
209 215 /home/git/share/gitolite/hooks/common/post-receive exists? ............YES
210 216  
211   -If you got all YES - congrats! You can go to next step.
  217 +If you got all YES - congratulations! You can go to the next step.
212 218  
213   -# 5. Server up
  219 +# 5. Start the web server
214 220  
215 221 Application can be started with next command:
216 222  
... ... @@ -225,12 +231,12 @@ You can login via web using admin generated with setup:
225 231 admin@local.host
226 232 5iveL!fe
227 233  
228   -# 6. Run resque process (for processing queue).
  234 +# 6. Run Resque process (for processing job queue).
229 235  
230 236 # Manually
231 237 sudo -u gitlab bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production BACKGROUND=yes
232 238  
233   - # Gitlab start script
  239 + # GitLab start script
234 240 sudo -u gitlab ./resque.sh
235 241 # if you run this as root /home/gitlab/gitlab/tmp/pids/resque_worker.pid will be owned by root
236 242 # causing the resque worker not to start via init script on next boot/service restart
... ... @@ -240,19 +246,19 @@ You can login via web using admin generated with setup:
240 246  
241 247 # Nginx && Unicorn
242 248  
243   -### Install Nginx
244   -
245   - sudo apt-get install nginx
246   -
247   -## Unicorn
  249 +## 1. Unicorn
248 250  
249 251 cd /home/gitlab/gitlab
250 252 sudo -u gitlab cp config/unicorn.rb.orig config/unicorn.rb
251 253 sudo -u gitlab bundle exec unicorn_rails -c config/unicorn.rb -E production -D
252 254  
253   -Add gitlab to nginx sites & change with your host specific settings
  255 +## 2. Nginx
  256 +
  257 + # Install first
  258 + sudo apt-get install nginx
254 259  
255   - sudo cp /home/gitlab/gitlab/lib/support/nginx-gitlab /etc/nginx/sites-available/gitlab
  260 + # Add GitLab to nginx sites & change with your host specific settings
  261 + sudo wget https://raw.github.com/gitlabhq/gitlab-recipes/master/nginx/gitlab -P /etc/nginx/sites-available/
256 262 sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab
257 263  
258 264 # Change **YOUR_SERVER_IP** and **YOUR_SERVER_FQDN**
... ... @@ -260,22 +266,21 @@ Add gitlab to nginx sites &amp; change with your host specific settings
260 266 # of the host serving GitLab.
261 267 sudo vim /etc/nginx/sites-enabled/gitlab
262 268  
263   -Restart nginx:
264 269  
  270 + # Restart nginx:
265 271 /etc/init.d/nginx restart
266 272  
267   -Create init script in /etc/init.d/gitlab:
268   -
269   - cp /home/gitlab/gitlab/lib/support/init-gitlab /etc/init.d/gitlab
  273 +## 3. Init script
270 274  
271   -Adding permission:
  275 +Create init script in /etc/init.d/gitlab:
272 276  
  277 + sudo wget https://raw.github.com/gitlabhq/gitlab-recipes/master/init.d/gitlab -P /etc/init.d/
273 278 sudo chmod +x /etc/init.d/gitlab
274 279  
275   -Gitlab autostart:
  280 +GitLab autostart:
276 281  
277 282 sudo update-rc.d gitlab defaults
278 283  
279   -Now you can start/restart/stop gitlab like:
  284 +Now you can start/restart/stop GitLab like:
280 285  
281 286 sudo /etc/init.d/gitlab restart
... ...
features/projects/issues/issues.feature
... ... @@ -4,7 +4,7 @@ Feature: Issues
4 4 And I own project "Shop"
5 5 And project "Shop" have "Release 0.4" open issue
6 6 And project "Shop" have "Release 0.3" closed issue
7   - And I visit project "Shop" issues page
  7 + And I visit project "Shop" issues page
8 8  
9 9 Scenario: I should see open issues
10 10 Given I should see "Release 0.4" in issues
... ... @@ -36,3 +36,31 @@ Feature: Issues
36 36 Given I visit issue page "Release 0.4"
37 37 And I leave a comment like "XML attached"
38 38 Then I should see comment "XML attached"
  39 +
  40 + @javascript
  41 + Scenario: I search issue
  42 + Given I fill in issue search with "Release"
  43 + Then I should see "Release 0.4" in issues
  44 + And I should not see "Release 0.3" in issues
  45 +
  46 + @javascript
  47 + Scenario: I search issue that not exist
  48 + Given I fill in issue search with "Bug"
  49 + Then I should not see "Release 0.4" in issues
  50 + And I should not see "Release 0.3" in issues
  51 +
  52 +
  53 + @javascript
  54 + Scenario: I search all issues
  55 + Given I click link "All"
  56 + And I fill in issue search with "0.3"
  57 + Then I should see "Release 0.3" in issues
  58 + And I should not see "Release 0.4" in issues
  59 +
  60 + @javascript
  61 + Scenario: I clear search
  62 + Given I click link "All"
  63 + And I fill in issue search with "Something"
  64 + And I fill in issue search with ""
  65 + Then I should see "Release 0.4" in issues
  66 + And I should see "Release 0.3" in issues
... ...
features/step_definitions/common_steps.rb 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +include LoginHelpers
  2 +
  3 +Given /^I signin as a user$/ do
  4 + login_as :user
  5 +end
  6 +
  7 +When /^I click link "(.*?)"$/ do |link|
  8 + click_link link
  9 +end
  10 +
  11 +When /^I click button "(.*?)"$/ do |button|
  12 + click_button button
  13 +end
  14 +
  15 +When /^I fill in "(.*?)" with "(.*?)"$/ do |field, value|
  16 + fill_in field, :with => value
  17 +end
  18 +
  19 +Given /^show me page$/ do
  20 + save_and_open_page
  21 +end
... ...
features/step_definitions/dashboard_steps.rb
1   -Given /^I visit dashboard page$/ do
2   - visit dashboard_path
3   -end
4   -
5 1 Then /^I should see "(.*?)" link$/ do |arg1|
6 2 page.should have_link(arg1)
7 3 end
... ... @@ -51,10 +47,10 @@ Then /^I click &quot;(.*?)&quot; link$/ do |arg1|
51 47 end
52 48  
53 49 Then /^I see prefilled new Merge Request page$/ do
54   - current_path.should == new_project_merge_request_path(@project)
55   - find("#merge_request_source_branch").value.should == "new_design"
56   - find("#merge_request_target_branch").value.should == "master"
57   - find("#merge_request_title").value.should == "New Design"
  50 + current_path.should == new_project_merge_request_path(@project)
  51 + find("#merge_request_source_branch").value.should == "new_design"
  52 + find("#merge_request_target_branch").value.should == "master"
  53 + find("#merge_request_title").value.should == "New Design"
58 54 end
59 55  
60 56 Given /^I visit dashboard search page$/ do
... ... @@ -66,10 +62,6 @@ Given /^I search for &quot;(.*?)&quot;$/ do |arg1|
66 62 click_button "Search"
67 63 end
68 64  
69   -Given /^I visit dashboard issues page$/ do
70   - visit dashboard_issues_path
71   -end
72   -
73 65 Then /^I should see issues assigned to me$/ do
74 66 issues = @user.issues
75 67 issues.each do |issue|
... ... @@ -78,10 +70,6 @@ Then /^I should see issues assigned to me$/ do
78 70 end
79 71 end
80 72  
81   -Given /^I visit dashboard merge requests page$/ do
82   - visit dashboard_merge_requests_path
83   -end
84   -
85 73 Then /^I should see my merge requests$/ do
86 74 merge_requests = @user.merge_requests
87 75 merge_requests.each do |mr|
... ...
features/step_definitions/profile/profile_steps.rb
1   -Given /^I visit profile page$/ do
2   - visit profile_path
3   -end
4   -
5 1 Then /^I should see my profile info$/ do
6 2 page.should have_content "Profile"
7 3 page.should have_content @user.name
8 4 page.should have_content @user.email
9 5 end
10 6  
11   -Given /^I visit profile password page$/ do
12   - visit profile_password_path
13   -end
14   -
15 7 Then /^I change my password$/ do
16 8 fill_in "user_password", :with => "222333"
17 9 fill_in "user_password_confirmation", :with => "222333"
... ... @@ -22,10 +14,6 @@ Then /^I should be redirected to sign in page$/ do
22 14 current_path.should == new_user_session_path
23 15 end
24 16  
25   -Given /^I visit profile token page$/ do
26   - visit profile_token_path
27   -end
28   -
29 17 Then /^I reset my token$/ do
30 18 @old_token = @user.private_token
31 19 click_button "Reset"
... ...
features/step_definitions/project/browse_code_steps.rb
1   -Given /^I visit project source page$/ do
2   - visit tree_project_ref_path(@project, @project.root_ref)
3   -end
4   -
5 1 Then /^I should see files from repository$/ do
6 2 page.should have_content("app")
7 3 page.should have_content("History")
8 4 page.should have_content("Gemfile")
9 5 end
10 6  
11   -Given /^I visit project source page for "(.*?)"$/ do |arg1|
12   - visit tree_project_ref_path(@project, arg1)
13   -end
14   -
15 7 Then /^I should see files from repository for "(.*?)"$/ do |arg1|
16 8 current_path.should == tree_project_ref_path(@project, arg1)
17 9 page.should have_content("app")
... ... @@ -31,10 +23,6 @@ Given /^I click on raw button$/ do
31 23 click_link "raw"
32 24 end
33 25  
34   -Given /^I visit blob file from repo$/ do
35   - visit tree_project_ref_path(@project, ValidCommit::ID, :path => ValidCommit::BLOB_FILE_PATH)
36   -end
37   -
38 26 Then /^I should see raw file content$/ do
39 27 page.source.should == ValidCommit::BLOB_FILE
40 28 end
... ...
features/step_definitions/project/project_commits_steps.rb
1   -Given /^I visit project commits page$/ do
2   - visit project_commits_path(@project)
3   -end
4   -
5 1 Then /^I see project commits$/ do
6 2 current_path.should == project_commits_path(@project)
7 3  
... ... @@ -23,19 +19,11 @@ Then /^I see commits atom feed$/ do
23 19 page.body.should have_selector("entry summary", :text => commit.description)
24 20 end
25 21  
26   -Given /^I click on commit link$/ do
27   - visit project_commit_path(@project, ValidCommit::ID)
28   -end
29   -
30 22 Then /^I see commit info$/ do
31 23 page.should have_content ValidCommit::MESSAGE
32 24 page.should have_content "Showing 1 changed file"
33 25 end
34 26  
35   -Given /^I visit compare refs page$/ do
36   - visit compare_project_commits_path(@project)
37   -end
38   -
39 27 Given /^I fill compare fields with refs$/ do
40 28 fill_in "from", :with => "master"
41 29 fill_in "to", :with => "stable"
... ... @@ -48,18 +36,6 @@ Given /^I see compared refs$/ do
48 36 page.should have_content "Showing 73 changed files"
49 37 end
50 38  
51   -Given /^I visit project branches page$/ do
52   - visit branches_project_repository_path(@project)
53   -end
54   -
55   -Given /^I visit project commit page$/ do
56   - visit project_commit_path(@project, ValidCommit::ID)
57   -end
58   -
59   -Given /^I visit project tags page$/ do
60   - visit tags_project_repository_path(@project)
61   -end
62   -
63 39 Then /^I should see "(.*?)" recent branches list$/ do |arg1|
64 40 page.should have_content("Branches")
65 41 page.should have_content("master")
... ... @@ -76,7 +52,7 @@ Then /^I should see &quot;(.*?)&quot; all tags list$/ do |arg1|
76 52 end
77 53  
78 54 Then /^I should see "(.*?)" protected branches list$/ do |arg1|
79   - within "table" do
  55 + within "table" do
80 56 page.should have_content "stable"
81 57 page.should_not have_content "master"
82 58 end
... ...
features/step_definitions/project/project_issues_steps.rb
... ... @@ -8,16 +8,12 @@ Given /^project &quot;(.*?)&quot; have &quot;(.*?)&quot; closed issue$/ do |arg1, arg2|
8 8 Factory.create(:issue, :title => arg2, :project => project, :author => project.users.first, :closed => true)
9 9 end
10 10  
11   -Given /^I visit project "(.*?)" issues page$/ do |arg1|
12   - visit project_issues_path(Project.find_by_name(arg1))
13   -end
14   -
15 11 Given /^I should see "(.*?)" in issues$/ do |arg1|
16   - page.should have_content arg1
  12 + page.should have_content arg1
17 13 end
18 14  
19 15 Given /^I should not see "(.*?)" in issues$/ do |arg1|
20   - page.should_not have_content arg1
  16 + page.should_not have_content arg1
21 17 end
22 18  
23 19 Then /^I should see issue "(.*?)"$/ do |arg1|
... ... @@ -27,11 +23,6 @@ Then /^I should see issue &quot;(.*?)&quot;$/ do |arg1|
27 23 page.should have_content issue.project.name
28 24 end
29 25  
30   -Given /^I visit issue page "(.*?)"$/ do |arg1|
31   - issue = Issue.find_by_title(arg1)
32   - visit project_issue_path(issue.project, issue)
33   -end
34   -
35 26 Given /^I submit new issue "(.*?)"$/ do |arg1|
36 27 fill_in "issue_title", with: arg1
37 28 click_button "Submit new issue"
... ... @@ -51,7 +42,16 @@ Given /^I visit project &quot;(.*?)&quot; labels page$/ do |arg1|
51 42 end
52 43  
53 44 Then /^I should see label "(.*?)"$/ do |arg1|
54   - within ".labels-table" do
  45 + within ".labels-table" do
55 46 page.should have_content arg1
56 47 end
57 48 end
  49 +
  50 +Given /^I fill in issue search with "(.*?)"$/ do |arg1|
  51 + # Because fill_in, with: "" triggers nothing
  52 + # we need to trigger a keyup event
  53 + if arg1 == ''
  54 + page.execute_script("$('.issue_search').val('').keyup();");
  55 + end
  56 + fill_in 'issue_search', with: arg1
  57 +end
... ...
features/step_definitions/project/project_merge_requests_steps.rb
... ... @@ -8,21 +8,17 @@ Given /^project &quot;(.*?)&quot; have &quot;(.*?)&quot; closed merge request$/ do |arg1, arg2|
8 8 Factory.create(:merge_request, :title => arg2, :project => project, :author => project.users.first, :closed => true)
9 9 end
10 10  
11   -Given /^I visit project "(.*?)" merge requests page$/ do |arg1|
12   - visit project_merge_requests_path(Project.find_by_name(arg1))
13   -end
14   -
15 11 Then /^I should see "(.*?)" in merge requests$/ do |arg1|
16   - page.should have_content arg1
  12 + page.should have_content arg1
17 13 end
18 14  
19 15 Then /^I should not see "(.*?)" in merge requests$/ do |arg1|
20   - page.should_not have_content arg1
  16 + page.should_not have_content arg1
21 17 end
22 18  
23 19 Then /^I should see merge request "(.*?)"$/ do |arg1|
24 20 merge_request = MergeRequest.find_by_title(arg1)
25   - page.should have_content(merge_request.title[0..10])
  21 + page.should have_content(merge_request.title[0..10])
26 22 page.should have_content(merge_request.target_branch)
27 23 page.should have_content(merge_request.source_branch)
28 24 end
... ... @@ -34,11 +30,6 @@ Given /^I submit new merge request &quot;(.*?)&quot;$/ do |arg1|
34 30 click_button "Save"
35 31 end
36 32  
37   -Given /^I visit merge request page "(.*?)"$/ do |arg1|
38   - mr = MergeRequest.find_by_title(arg1)
39   - visit project_merge_request_path(mr.project, mr)
40   -end
41   -
42 33 Then /^I should see closed merge request "(.*?)"$/ do |arg1|
43 34 mr = MergeRequest.find_by_title(arg1)
44 35 mr.closed.should be_true
... ...
features/step_definitions/project/project_milestones_steps.rb
... ... @@ -12,11 +12,6 @@ Given /^project &quot;(.*?)&quot; has milestone &quot;(.*?)&quot;$/ do |arg1, arg2|
12 12 end
13 13 end
14 14  
15   -Given /^I visit project "(.*?)" milestones page$/ do |arg1|
16   - @project = Project.find_by_name(arg1)
17   - visit project_milestones_path(@project)
18   -end
19   -
20 15 Then /^I should see active milestones$/ do
21 16 milestone = @project.milestones.first
22 17 page.should have_content(milestone.title[0..10])
... ...
features/step_definitions/project/project_team_steps.rb
... ... @@ -8,10 +8,6 @@ Given /^&quot;(.*?)&quot; is &quot;(.*?)&quot; developer$/ do |arg1, arg2|
8 8 project.add_access(user, :write)
9 9 end
10 10  
11   -Given /^I visit project "(.*?)" team page$/ do |arg1|
12   - visit team_project_path(Project.find_by_name(arg1))
13   -end
14   -
15 11 Then /^I should be able to see myself in team$/ do
16 12 page.should have_content(@user.name)
17 13 page.should have_content(@user.email)
... ... @@ -23,13 +19,9 @@ Then /^I should see &quot;(.*?)&quot; in team list$/ do |arg1|
23 19 page.should have_content(user.email)
24 20 end
25 21  
26   -Given /^I click link "(.*?)"$/ do |arg1|
27   - click_link arg1
28   -end
29   -
30 22 Given /^I select "(.*?)" as "(.*?)"$/ do |arg1, arg2|
31 23 user = User.find_by_name(arg1)
32   - within "#new_team_member" do
  24 + within "#new_team_member" do
33 25 select user.name, :from => "team_member_user_id"
34 26 select arg2, :from => "team_member_project_access"
35 27 end
... ... @@ -44,7 +36,7 @@ end
44 36  
45 37 Given /^I change "(.*?)" role to "(.*?)"$/ do |arg1, arg2|
46 38 user = User.find_by_name(arg1)
47   - within ".user_#{user.id}" do
  39 + within ".user_#{user.id}" do
48 40 select arg2, :from => "team_member_project_access"
49 41 end
50 42 end
... ...
features/step_definitions/project/project_wiki_steps.rb
1   -Given /^I visit project wiki page$/ do
2   - visit project_wiki_path(@project, :index)
3   -end
4   -
5 1 Given /^I create Wiki page$/ do
6 2 fill_in "Title", :with => 'Test title'
7 3 fill_in "Content", :with => '[link test](test)'
... ...
features/step_definitions/project/projects_steps.rb
1   -include LoginHelpers
2   -
3   -Given /^I signin as a user$/ do
4   - login_as :user
5   -end
6   -
7 1 When /^I visit new project page$/ do
8 2 visit new_project_path
9 3 end
... ... @@ -65,10 +59,6 @@ Given /^I visit project &quot;(.*?)&quot; network page$/ do |arg1|
65 59 visit graph_project_path(project)
66 60 end
67 61  
68   -Given /^show me page$/ do
69   - save_and_open_page
70   -end
71   -
72 62 Given /^page should have network graph$/ do
73 63 page.should have_content "Project Network Graph"
74 64 within ".graph" do
... ...
features/step_definitions/visit_steps.rb 0 → 100644
... ... @@ -0,0 +1,91 @@
  1 +Given /^I visit project "(.*?)" issues page$/ do |arg1|
  2 + visit project_issues_path(Project.find_by_name(arg1))
  3 +end
  4 +
  5 +Given /^I visit issue page "(.*?)"$/ do |arg1|
  6 + issue = Issue.find_by_title(arg1)
  7 + visit project_issue_path(issue.project, issue)
  8 +end
  9 +
  10 +Given /^I visit project "(.*?)" merge requests page$/ do |arg1|
  11 + visit project_merge_requests_path(Project.find_by_name(arg1))
  12 +end
  13 +
  14 +Given /^I visit merge request page "(.*?)"$/ do |arg1|
  15 + mr = MergeRequest.find_by_title(arg1)
  16 + visit project_merge_request_path(mr.project, mr)
  17 +end
  18 +
  19 +Given /^I visit project "(.*?)" milestones page$/ do |arg1|
  20 + @project = Project.find_by_name(arg1)
  21 + visit project_milestones_path(@project)
  22 +end
  23 +
  24 +Given /^I visit project commits page$/ do
  25 + visit project_commits_path(@project)
  26 +end
  27 +
  28 +Given /^I visit compare refs page$/ do
  29 + visit compare_project_commits_path(@project)
  30 +end
  31 +
  32 +Given /^I visit project branches page$/ do
  33 + visit branches_project_repository_path(@project)
  34 +end
  35 +
  36 +Given /^I visit project commit page$/ do
  37 + visit project_commit_path(@project, ValidCommit::ID)
  38 +end
  39 +
  40 +Given /^I visit project tags page$/ do
  41 + visit tags_project_repository_path(@project)
  42 +end
  43 +
  44 +Given /^I click on commit link$/ do
  45 + visit project_commit_path(@project, ValidCommit::ID)
  46 +end
  47 +
  48 +Given /^I visit project source page$/ do
  49 + visit tree_project_ref_path(@project, @project.root_ref)
  50 +end
  51 +
  52 +Given /^I visit project source page for "(.*?)"$/ do |arg1|
  53 + visit tree_project_ref_path(@project, arg1)
  54 +end
  55 +
  56 +Given /^I visit blob file from repo$/ do
  57 + visit tree_project_ref_path(@project, ValidCommit::ID, :path => ValidCommit::BLOB_FILE_PATH)
  58 +end
  59 +
  60 +Given /^I visit project "(.*?)" team page$/ do |arg1|
  61 + visit team_project_path(Project.find_by_name(arg1))
  62 +end
  63 +
  64 +Given /^I visit project wiki page$/ do
  65 + visit project_wiki_path(@project, :index)
  66 +end
  67 +
  68 +Given /^I visit profile page$/ do
  69 + visit profile_path
  70 +end
  71 +
  72 +Given /^I visit profile token page$/ do
  73 + visit profile_token_path
  74 +end
  75 +
  76 +Given /^I visit profile password page$/ do
  77 + visit profile_password_path
  78 +end
  79 +
  80 +Given /^I visit dashboard page$/ do
  81 + visit dashboard_path
  82 +end
  83 +
  84 +Given /^I visit dashboard issues page$/ do
  85 + visit dashboard_issues_path
  86 +end
  87 +
  88 +Given /^I visit dashboard merge requests page$/ do
  89 + visit dashboard_merge_requests_path
  90 +end
  91 +
... ...
lib/api/projects.rb
... ... @@ -29,14 +29,24 @@ module Gitlab
29 29 # name (required) - name for new project
30 30 # code (optional) - code for new project, uses project name if not set
31 31 # path (optional) - path for new project, uses project name if not set
  32 + # description (optional) - short project description
  33 + # default_branch (optional) - 'master' by default
  34 + # issues_enabled (optional) - enabled by default
  35 + # wall_enabled (optional) - enabled by default
  36 + # merge_requests_enabled (optional) - enabled by default
  37 + # wiki_enabled (optional) - enabled by default
32 38 # Example Request
33 39 # POST /projects
34 40 post do
35   - project = {}
36   - project[:name] = params[:name]
37   - project[:code] = params[:code] || project[:name]
38   - project[:path] = params[:path] || project[:name]
39   - @project = Project.create_by_user(project, current_user)
  41 + params[:code] ||= params[:name]
  42 + params[:path] ||= params[:name]
  43 + project_attrs = {}
  44 + params.each_pair do |k ,v|
  45 + if Project.attribute_names.include? k
  46 + project_attrs[k] = v
  47 + end
  48 + end
  49 + @project = Project.create_by_user(project_attrs, current_user)
40 50 if @project.saved?
41 51 present @project, with: Entities::Project
42 52 else
... ...
lib/gitlab/backend/gitolite.rb
... ... @@ -170,7 +170,7 @@ module Gitlab
170 170 def push
171 171 Dir.chdir(File.join(@local_dir, "gitolite"))
172 172 `git add -A`
173   - `git commit -am "Gitlab"`
  173 + `git commit -am "GitLab"`
174 174 `git push`
175 175 Dir.chdir(Rails.root)
176 176  
... ...
lib/gitlab/markdown.rb
1 1 module Gitlab
2   - # Custom parser for Gitlab-flavored Markdown
  2 + # Custom parser for GitLab-flavored Markdown
3 3 #
4   - # It replaces references in the text with links to the appropriate items in Gitlab.
  4 + # It replaces references in the text with links to the appropriate items in
  5 + # GitLab.
5 6 #
6 7 # Supported reference formats are:
7 8 # * @foo for team members
... ... @@ -10,19 +11,20 @@ module Gitlab
10 11 # * $123 for snippets
11 12 # * 123456 for commits
12 13 #
13   - # Examples
  14 + # It also parses Emoji codes to insert images. See
  15 + # http://www.emoji-cheat-sheet.com/ for a list of the supported icons.
14 16 #
15   - # >> m = Markdown.new(...)
  17 + # Examples
16 18 #
17   - # >> m.parse("Hey @david, can you fix this?")
  19 + # >> gfm("Hey @david, can you fix this?")
18 20 # => "Hey <a href="/gitlab/team_members/1">@david</a>, can you fix this?"
19 21 #
20   - # >> m.parse("Commit 35d5f7c closes #1234")
  22 + # >> gfm("Commit 35d5f7c closes #1234")
21 23 # => "Commit <a href="/gitlab/commits/35d5f7c">35d5f7c</a> closes <a href="/gitlab/issues/1234">#1234</a>"
22   - class Markdown
23   - include Rails.application.routes.url_helpers
24   - include ActionView::Helpers
25   -
  24 + #
  25 + # >> gfm(":trollface:")
  26 + # => "<img alt=\":trollface:\" class=\"emoji\" src=\"/images/trollface.png" title=\":trollface:\" />
  27 + module Markdown
26 28 REFERENCE_PATTERN = %r{
27 29 ([^\w&;])? # Prefix (1)
28 30 ( # Reference (2)
... ... @@ -33,15 +35,52 @@ module Gitlab
33 35 ([^\w&;])? # Suffix (6)
34 36 }x.freeze
35 37  
  38 + EMOJI_PATTERN = %r{(:(\S+):)}.freeze
  39 +
36 40 attr_reader :html_options
37 41  
38   - def initialize(project, html_options = {})
39   - @project = project
  42 + # Public: Parse the provided text with GitLab-Flavored Markdown
  43 + #
  44 + # text - the source text
  45 + # html_options - extra options for the reference links as given to link_to
  46 + #
  47 + # Note: reference links will only be generated if @project is set
  48 + def gfm(text, html_options = {})
  49 + return text if text.nil?
  50 + return text if @project.nil?
  51 +
40 52 @html_options = html_options
  53 +
  54 + # Extract pre blocks so they are not altered
  55 + # from http://github.github.com/github-flavored-markdown/
  56 + extractions = {}
  57 + text.gsub!(%r{<pre>.*?</pre>|<code>.*?</code>}m) do |match|
  58 + md5 = Digest::MD5.hexdigest(match)
  59 + extractions[md5] = match
  60 + "{gfm-extraction-#{md5}}"
  61 + end
  62 +
  63 + # TODO: add popups with additional information
  64 +
  65 + text = parse(text)
  66 +
  67 + # Insert pre block extractions
  68 + text.gsub!(/\{gfm-extraction-(\h{32})\}/) do
  69 + extractions[$1]
  70 + end
  71 +
  72 + sanitize text.html_safe, attributes: ActionView::Base.sanitized_allowed_attributes + %w(id class)
41 73 end
42 74  
  75 + private
  76 +
  77 + # Private: Parses text for references and emoji
  78 + #
  79 + # text - Text to parse
  80 + #
  81 + # Returns parsed text
43 82 def parse(text)
44   - text.gsub(REFERENCE_PATTERN) do |match|
  83 + text = text.gsub(REFERENCE_PATTERN) do |match|
45 84 prefix = $1 || ''
46 85 reference = $2
47 86 identifier = $3 || $4 || $5
... ... @@ -53,9 +92,26 @@ module Gitlab
53 92 match
54 93 end
55 94 end
  95 +
  96 + text = text.gsub(EMOJI_PATTERN) do |match|
  97 + if valid_emoji?($2)
  98 + image_tag("emoji/#{$2}.png", size: "20x20", class: 'emoji', title: $1, alt: $1)
  99 + else
  100 + match
  101 + end
  102 + end
  103 +
  104 + text
56 105 end
57 106  
58   - private
  107 + # Private: Checks if an emoji icon exists in the image asset directory
  108 + #
  109 + # emoji - Identifier of the emoji as a string (e.g., "+1", "heart")
  110 + #
  111 + # Returns boolean
  112 + def valid_emoji?(emoji)
  113 + File.exists?(Rails.root.join('app', 'assets', 'images', 'emoji', "#{emoji}.png"))
  114 + end
59 115  
60 116 # Private: Dispatches to a dedicated processing method based on reference
61 117 #
... ...
lib/hooks/post-receive
1 1 #!/usr/bin/env bash
2 2  
3   -# This file was placed here by Gitlab. It makes sure that your pushed commits
  3 +# This file was placed here by GitLab. It makes sure that your pushed commits
4 4 # will be processed properly.
5 5  
6 6 while read oldrev newrev ref
... ...
lib/support/aws/debian_ubuntu_aws.sh
... ... @@ -1,122 +0,0 @@
1   -#!/bin/sh
2   -
3   -# ABOUT
4   -# This script performs a complete installation of Gitlab (master branch).
5   -# Is can be run with one command without needing _any_ user input after that.
6   -# This script only works on Amazon Web Services (AWS).
7   -# The operating system used is Ubuntu 12.04 64bit.
8   -
9   -# HOWTO
10   -# Signup for AWS, free tier are available at http://aws.amazon.com/free/
11   -# Go to EC2 tab in the AWS console EC2 https://console.aws.amazon.com/ec2/home
12   -# Click the 'Launch Instance' button
13   -# Select: 'Quick launch wizard' and continue
14   -# Choose a key pair => Create New => Name it => Download it
15   -# Choose a Launch Configuration => Select 'More Amazon Marketplace Images'
16   -# Press 'Continue'
17   -# Enter 'ubuntu/images/ubuntu-precise-12.04-amd64-server-20120424' and press 'Search'
18   -# Select the only result (ami-3c994355) and press 'Continue'
19   -# Press 'Edit details' if you want to modify something, for example make the type 'c1.medium' to make the install faster.
20   -# Press the 'Launch' button
21   -# Press 'Close'
22   -# Click 'Security Groups' under the left hand menu 'NETWORK & SECURITY'
23   -# Select the newly create seciruty group, probably named 'quicklaunch-1'
24   -# Click on the Inbound tab
25   -# In the 'Create a new rule' dropdown select 'HTTP'
26   -# Press 'Add Rule'
27   -# In the 'Create a new rule' dropdown select 'HTTPS'
28   -# Press 'Add Rule'
29   -# Press 'Apply Rule Changes'
30   -# Give the following command in your local terminal while suptituting the UPPERCASE items
31   -# 'ssh -i LOCATION_OF_AWS_KEY_PAIR_PRIVATE_KEY PUBLIC_DNS_OF_THE_NEW_SERVER'
32   -# Execute the curl command below and when its ready follow the printed 'Log in instuctions'
33   -# curl https://raw.github.com/gitlabhq/gitlabhq/master/lib/support/aws/debian_ubuntu_aws.sh | sh
34   -
35   -# Prevent fingerprint prompt for localhost in step 1 to 3.
36   -echo "Host localhost
37   - StrictHostKeyChecking no
38   - UserKnownHostsFile=/dev/null" | sudo tee -a /etc/ssh/ssh_config
39   -
40   -# Existing script for Step 1 to 3
41   -curl https://raw.github.com/gitlabhq/gitlabhq/master/doc/debian_ubuntu.sh | sh
42   -
43   -# Install MySQL
44   -sudo apt-get install -y makepasswd # Needed to create a unique password non-interactively.
45   -userPassword=$(makepasswd --char=10) # Generate a random MySQL password
46   -# Note that the lines below creates a cleartext copy of the random password in /var/cache/debconf/passwords.dat
47   -# This file is normally only readable by root and the password will be deleted by the package management system after install.
48   -echo mysql-server mysql-server/root_password password $userPassword | sudo debconf-set-selections
49   -echo mysql-server mysql-server/root_password_again password $userPassword | sudo debconf-set-selections
50   -sudo apt-get install -y mysql-server
51   -
52   -# Gitlab install
53   -sudo gem install charlock_holmes --version '0.6.8'
54   -sudo pip install pygments
55   -sudo gem install bundler
56   -sudo su -l gitlab -c "git clone git://github.com/gitlabhq/gitlabhq.git gitlab" # Using master everywhere.
57   -sudo su -l gitlab -c "cd gitlab && mkdir tmp"
58   -sudo su -l gitlab -c "cd gitlab/config && cp gitlab.yml.example gitlab.yml"
59   -sudo su -l gitlab -c "cd gitlab/config && cp database.yml.example database.yml"
60   -sudo sed -i 's/"secure password"/"'$userPassword'"/' /home/gitlab/gitlab/config/database.yml # Insert the mysql root password.
61   -sudo su -l gitlab -c "cd gitlab && bundle install --without development test --deployment"
62   -sudo su -l gitlab -c "cd gitlab && bundle exec rake gitlab:app:setup RAILS_ENV=production"
63   -
64   -# Setup gitlab hooks
65   -sudo cp /home/gitlab/gitlab/lib/hooks/post-receive /home/git/share/gitolite/hooks/common/post-receive
66   -sudo chown git:git /home/git/share/gitolite/hooks/common/post-receive
67   -
68   -# Set the first occurrence of host in the Gitlab config to the publicly available domain name
69   -sudo sed -i '0,/host/s/localhost/'`wget -qO- http://instance-data/latest/meta-data/public-hostname`'/' /home/gitlab/gitlab/config/gitlab.yml
70   -
71   -# Gitlab installation test (optional)
72   -# sudo -u gitlab bundle exec rake gitlab:app:status RAILS_ENV=production
73   -# sudo -u gitlab bundle exec rails s -e production
74   -# sudo -u gitlab bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production BACKGROUND=no
75   -
76   -# Install and configure Nginx
77   -sudo apt-get install -y nginx
78   -sudo cp /home/gitlab/gitlab/lib/support/nginx-gitlab /etc/nginx/sites-available/gitlab
79   -sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab
80   -sudo sed -i 's/YOUR_SERVER_IP/'`wget -qO- http://instance-data/latest/meta-data/local-ipv4`'/' /etc/nginx/sites-available/gitlab # Set private ip address (public won't work).
81   -sudo sed -i 's/YOUR_SERVER_FQDN/'`wget -qO- http://instance-data/latest/meta-data/public-hostname`'/' /etc/nginx/sites-available/gitlab # Set public dns domain name.
82   -
83   -# Configure Unicorn
84   -sudo -u gitlab cp /home/gitlab/gitlab/config/unicorn.rb.orig /home/gitlab/gitlab/config/unicorn.rb
85   -
86   -# Create a Gitlab service
87   -sudo cp /home/gitlab/gitlab/lib/support/init-gitlab /etc/init.d/gitlab
88   -sudo chmod +x /etc/init.d/gitlab && sudo update-rc.d gitlab defaults
89   -
90   -## Gitlab service commands (unicorn and resque)
91   -## restart doesn't restart resque, only start/stop effect it.
92   -sudo -u gitlab service gitlab start
93   -# sudo -u gitlab service gitlab restart
94   -# sudo -u gitlab service gitlab stop
95   -
96   -# nginx Service commands
97   -# sudo service nginx start
98   -sudo service nginx restart
99   -# sudo service nginx stop
100   -
101   -# Manual startup commands for troubleshooting when the service commands do not work
102   -# sudo -u gitlab bundle exec unicorn_rails -c config/unicorn.rb -E production -D
103   -# sudo su -l gitlab -c "cd gitlab && ./resque.sh"
104   -
105   -# Monitoring commands
106   -# sudo tail -f /var/log/nginx/access.log;
107   -# sudo tail -f /var/log/nginx/error.log;
108   -
109   -# Go to gitlab directory by default on next login.
110   -echo 'cd /home/gitlab/gitlab' >> /home/ubuntu/.bashrc
111   -
112   -echo ''
113   -echo '###########################################'
114   -echo '# Log in instuctions #'
115   -echo '###########################################'
116   -echo ''
117   -echo "Surf to this Gitlab installation in your browser:"
118   -echo "http://`wget -qO- http://instance-data/latest/meta-data/public-hostname`/"
119   -echo ''
120   -echo 'and login with the following Email and Password:'
121   -echo 'admin@local.host'
122   -echo '5iveL!fe'
123 0 \ No newline at end of file
lib/support/init-gitlab
... ... @@ -1,54 +0,0 @@
1   -#! /bin/bash
2   -### BEGIN INIT INFO
3   -# Provides: gitlab
4   -# Required-Start: $local_fs $remote_fs $network $syslog redis-server
5   -# Required-Stop: $local_fs $remote_fs $network $syslog
6   -# Default-Start: 2 3 4 5
7   -# Default-Stop: 0 1 6
8   -# Short-Description: GitLab git repository management
9   -# Description: GitLab git repository management
10   -### END INIT INFO
11   -
12   -DAEMON_OPTS="-c /home/gitlab/gitlab/config/unicorn.rb -E production -D"
13   -NAME=unicorn
14   -DESC="Gitlab service"
15   -PID=/home/gitlab/gitlab/tmp/pids/unicorn.pid
16   -RESQUE_PID=/home/gitlab/gitlab/tmp/pids/resque_worker.pid
17   -
18   -case "$1" in
19   - start)
20   - CD_TO_APP_DIR="cd /home/gitlab/gitlab"
21   - START_DAEMON_PROCESS="bundle exec unicorn_rails $DAEMON_OPTS"
22   - START_RESQUE_PROCESS="./resque.sh"
23   -
24   - echo -n "Starting $DESC: "
25   - if [ `whoami` = root ]; then
26   - sudo -u gitlab sh -l -c "$CD_TO_APP_DIR > /dev/null 2>&1 && $START_DAEMON_PROCESS && $START_RESQUE_PROCESS"
27   - else
28   - $CD_TO_APP_DIR > /dev/null 2>&1 && $START_DAEMON_PROCESS && $START_RESQUE_PROCESS
29   - fi
30   - echo "$NAME."
31   - ;;
32   - stop)
33   - echo -n "Stopping $DESC: "
34   - kill -QUIT `cat $PID`
35   - kill -QUIT `cat $RESQUE_PID`
36   - echo "$NAME."
37   - ;;
38   - restart)
39   - echo -n "Restarting $DESC: "
40   - kill -USR2 `cat $PID`
41   - echo "$NAME."
42   - ;;
43   - reload)
44   - echo -n "Reloading $DESC configuration: "
45   - kill -HUP `cat $PID`
46   - echo "$NAME."
47   - ;;
48   - *)
49   - echo "Usage: $NAME {start|stop|restart|reload}" >&2
50   - exit 1
51   - ;;
52   -esac
53   -
54   -exit 0
lib/support/nginx-gitlab
... ... @@ -1,33 +0,0 @@
1   -upstream gitlab {
2   - server unix:/home/gitlab/gitlab/tmp/sockets/gitlab.socket;
3   -}
4   -
5   -server {
6   - listen YOUR_SERVER_IP:80; # e.g., listen 192.168.1.1:80;
7   - server_name YOUR_SERVER_FQDN; # e.g., server_name source.example.com;
8   - root /home/gitlab/gitlab/public;
9   -
10   - # individual nginx logs for this gitlab vhost
11   - access_log /var/log/nginx/gitlab_access.log;
12   - error_log /var/log/nginx/gitlab_error.log;
13   -
14   - location / {
15   - # serve static files from defined root folder;.
16   - # @gitlab is a named location for the upstream fallback, see below
17   - try_files $uri $uri/index.html $uri.html @gitlab;
18   - }
19   -
20   - # if a file, which is not found in the root folder is requested,
21   - # then the proxy pass the request to the upsteam (gitlab unicorn)
22   - location @gitlab {
23   - proxy_redirect off;
24   -
25   - # you need to change this to "https", if you set "ssl" directive to "on"
26   - proxy_set_header X-FORWARDED_PROTO http;
27   - proxy_set_header Host $http_host;
28   - proxy_set_header X-Real-IP $remote_addr;
29   -
30   - proxy_pass http://gitlab;
31   - }
32   -}
33   -
lib/tasks/bulk_import.rake
1 1 IMPORT_DIRECTORY = 'import_projects'
2   -REPOSITORY_DIRECTORY = '/home/git/repositories'
3 2  
4 3 desc "Imports existing Git repos into new projects from the import_projects folder"
5 4 task :import_projects, [:email] => :environment do |t, args|
  5 + REPOSITORY_DIRECTORY = Gitlab.config.git_base_path
  6 +
6 7 user_email = args.email
7 8 repos_to_import = Dir.glob("#{IMPORT_DIRECTORY}/*")
8 9  
... ...
lib/tasks/gitlab/write_hook.rake
1 1 namespace :gitlab do
2 2 namespace :gitolite do
3   - desc "GITLAB | Write GITLAB hook for gitolite"
  3 + desc "GITLAB | Write GitLab hook for gitolite"
4 4 task :write_hooks => :environment do
5 5 gitolite_hooks_path = File.join(Gitlab.config.git_hooks_path, "common")
6 6 gitlab_hooks_path = Rails.root.join("lib", "hooks")
... ...
spec/factories.rb
... ... @@ -11,6 +11,9 @@ module Factory
11 11 def self.new(type, *args)
12 12 FactoryGirl.build(type, *args)
13 13 end
  14 + def self.attributes(type, *args)
  15 + FactoryGirl.attributes_for(type, *args)
  16 + end
14 17 end
15 18  
16 19 FactoryGirl.define do
... ... @@ -28,7 +31,7 @@ FactoryGirl.define do
28 31 email { Faker::Internet.email }
29 32 name
30 33 password "123456"
31   - password_confirmation "123456"
  34 + password_confirmation { password }
32 35  
33 36 trait :admin do
34 37 admin true
... ...
spec/factories_spec.rb
1 1 require 'spec_helper'
2 2  
3   -describe "Factories" do
4   - describe 'User' do
5   - it "builds a valid instance" do
6   - build(:user).should be_valid
7   - end
8   -
9   - it "builds a valid admin instance" do
10   - build(:admin).should be_valid
11   - end
12   - end
13   -
14   - describe 'Project' do
15   - it "builds a valid instance" do
16   - build(:project).should be_valid
17   - end
18   - end
19   -
20   - describe 'Issue' do
21   - it "builds a valid instance" do
22   - build(:issue).should be_valid
23   - end
24   -
25   - it "builds a valid closed instance" do
26   - build(:closed_issue).should be_valid
27   - end
28   - end
29   -
30   - describe 'MergeRequest' do
31   - it "builds a valid instance" do
32   - build(:merge_request).should be_valid
33   - end
34   - end
35   -
36   - describe 'Note' do
37   - it "builds a valid instance" do
38   - build(:note).should be_valid
39   - end
40   - end
41   -
42   - describe 'Event' do
43   - it "builds a valid instance" do
44   - build(:event).should be_valid
45   - end
46   - end
47   -
48   - describe 'Key' do
49   - it "builds a valid instance" do
50   - build(:key).should be_valid
51   - end
52   -
53   - it "builds a valid deploy key instance" do
54   - build(:deploy_key).should be_valid
55   - end
56   -
57   - it "builds a valid personal key instance" do
58   - build(:personal_key).should be_valid
59   - end
60   - end
61   -
62   - describe 'Milestone' do
63   - it "builds a valid instance" do
64   - build(:milestone).should be_valid
65   - end
66   - end
67   -
68   - describe 'SystemHook' do
69   - it "builds a valid instance" do
70   - build(:system_hook).should be_valid
71   - end
72   - end
73   -
74   - describe 'ProjectHook' do
75   - it "builds a valid instance" do
76   - build(:project_hook).should be_valid
77   - end
78   - end
79   -
80   - describe 'Wiki' do
81   - it "builds a valid instance" do
82   - build(:wiki).should be_valid
83   - end
84   - end
85   -
86   - describe 'Snippet' do
87   - it "builds a valid instance" do
88   - build(:snippet).should be_valid
  3 +FactoryGirl.factories.map(&:name).each do |factory_name|
  4 + describe "#{factory_name} factory" do
  5 + it 'should be valid' do
  6 + build(factory_name).should be_valid
89 7 end
90 8 end
91 9 end
... ...
spec/helpers/gitlab_markdown_helper_spec.rb
... ... @@ -208,6 +208,46 @@ describe GitlabMarkdownHelper do
208 208 gfm(actual).should match(expected)
209 209 end
210 210 end
  211 +
  212 + describe "emoji" do
  213 + it "matches at the start of a string" do
  214 + gfm(":+1:").should match(/<img/)
  215 + end
  216 +
  217 + it "matches at the end of a string" do
  218 + gfm("This gets a :-1:").should match(/<img/)
  219 + end
  220 +
  221 + it "matches with adjacent text" do
  222 + gfm("+1 (:+1:)").should match(/<img/)
  223 + end
  224 +
  225 + it "has a title attribute" do
  226 + gfm(":-1:").should match(/title=":-1:"/)
  227 + end
  228 +
  229 + it "has an alt attribute" do
  230 + gfm(":-1:").should match(/alt=":-1:"/)
  231 + end
  232 +
  233 + it "has an emoji class" do
  234 + gfm(":+1:").should match('class="emoji"')
  235 + end
  236 +
  237 + it "sets height and width" do
  238 + actual = gfm(":+1:")
  239 + actual.should match(/width="20"/)
  240 + actual.should match(/height="20"/)
  241 + end
  242 +
  243 + it "keeps whitespace intact" do
  244 + gfm("This deserves a :+1: big time.").should match(/deserves a <img.+\/> big time/)
  245 + end
  246 +
  247 + it "ignores invalid emoji" do
  248 + gfm(":invalid-emoji:").should_not match(/<img/)
  249 + end
  250 + end
211 251 end
212 252  
213 253 describe "#link_to_gfm" do
... ...
spec/mailers/notify_spec.rb
... ... @@ -24,7 +24,7 @@ describe Notify do
24 24 end
25 25  
26 26 it 'has the correct subject' do
27   - should have_subject /^gitlab \| Account was created for you$/
  27 + should have_subject /^gitlab \| Account was created for you$/i
28 28 end
29 29  
30 30 it 'contains the new user\'s login name' do
... ...
spec/models/issue_spec.rb
... ... @@ -7,6 +7,7 @@ describe Issue do
7 7  
8 8 describe "Validation" do
9 9 it { should ensure_length_of(:description).is_within(0..2000) }
  10 + it { should ensure_inclusion_of(:closed).in_array([true, false]) }
10 11 end
11 12  
12 13 describe 'modules' do
... ...
spec/models/milestone_spec.rb
... ... @@ -9,6 +9,7 @@ describe Milestone do
9 9 describe "Validation" do
10 10 it { should validate_presence_of(:title) }
11 11 it { should validate_presence_of(:project_id) }
  12 + it { should ensure_inclusion_of(:closed).in_array([true, false]) }
12 13 end
13 14  
14 15 let(:milestone) { Factory :milestone }
... ...
spec/models/note_spec.rb
... ... @@ -35,6 +35,16 @@ describe Note do
35 35 note = Factory(:note, note: "-1 for this")
36 36 note.should_not be_upvote
37 37 end
  38 +
  39 + it "recognizes a +1 emoji as a vote" do
  40 + note = build(:note, note: ":+1: for this")
  41 + note.should be_upvote
  42 + end
  43 +
  44 + it "recognizes a neutral emoji note" do
  45 + note = build(:note, note: "I would :+1: this, but I don't want to")
  46 + note.should_not be_upvote
  47 + end
38 48 end
39 49  
40 50 let(:project) { create(:project) }
... ...
spec/models/project_spec.rb
... ... @@ -37,6 +37,10 @@ describe Project do
37 37 # TODO: Formats
38 38  
39 39 it { should validate_presence_of(:owner) }
  40 + it { should ensure_inclusion_of(:issues_enabled).in_array([true, false]) }
  41 + it { should ensure_inclusion_of(:wall_enabled).in_array([true, false]) }
  42 + it { should ensure_inclusion_of(:merge_requests_enabled).in_array([true, false]) }
  43 + it { should ensure_inclusion_of(:wiki_enabled).in_array([true, false]) }
40 44  
41 45 it "should not allow new projects beyond user limits" do
42 46 project.stub(:owner).and_return(double(can_create_project?: false, projects_limit: 1))
... ... @@ -239,7 +243,7 @@ describe Project do
239 243 end
240 244 end
241 245  
242   - describe :update_merge_requests do
  246 + describe :update_merge_requests do
243 247 let(:project) { Factory :project }
244 248  
245 249 before do
... ... @@ -259,7 +263,7 @@ describe Project do
259 263 @merge_request.closed.should be_true
260 264 end
261 265  
262   - it "should update merge request commits with new one if pushed to source branch" do
  266 + it "should update merge request commits with new one if pushed to source branch" do
263 267 @merge_request.last_commit.should == nil
264 268 project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/master", @key.user)
265 269 @merge_request.reload
... ...
spec/models/user_spec.rb
... ... @@ -31,36 +31,46 @@ describe User do
31 31 it { should respond_to(:private_token) }
32 32 end
33 33  
34   - it "should return valid identifier" do
35   - user = User.new(email: "test@mail.com")
36   - user.identifier.should == "test_mail_com"
37   - end
  34 + describe '#identifier' do
  35 + it "should return valid identifier" do
  36 + user = build(:user, email: "test@mail.com")
  37 + user.identifier.should == "test_mail_com"
  38 + end
38 39  
39   - it "should return identifier without + sign" do
40   - user = User.new(email: "test+foo@mail.com")
41   - user.identifier.should == "test_foo_mail_com"
42   - end
  40 + it "should return identifier without + sign" do
  41 + user = build(:user, email: "test+foo@mail.com")
  42 + user.identifier.should == "test_foo_mail_com"
  43 + end
43 44  
44   - it "should execute callback when force_random_password specified" do
45   - user = User.new(email: "test@mail.com", force_random_password: true)
46   - user.should_receive(:generate_password)
47   - user.save
  45 + it "should conform to Gitolite's required identifier pattern" do
  46 + user = build(:user, email: "_test@example.com")
  47 + user.identifier.should == 'test_example_com'
  48 + end
48 49 end
49 50  
50   - it "should not generate password by default" do
51   - user = Factory(:user, password: 'abcdefg', password_confirmation: 'abcdefg')
52   - user.password.should == 'abcdefg'
53   - end
  51 + describe '#generate_password' do
  52 + it "should execute callback when force_random_password specified" do
  53 + user = build(:user, force_random_password: true)
  54 + user.should_receive(:generate_password)
  55 + user.save
  56 + end
  57 +
  58 + it "should not generate password by default" do
  59 + user = create(:user, password: 'abcdefg')
  60 + user.password.should == 'abcdefg'
  61 + end
54 62  
55   - it "should generate password when forcing random password" do
56   - Devise.stub(:friendly_token).and_return('123456789')
57   - user = User.create(email: "test1@mail.com", force_random_password: true)
58   - user.password.should == user.password_confirmation
59   - user.password.should == '12345678'
  63 + it "should generate password when forcing random password" do
  64 + Devise.stub(:friendly_token).and_return('123456789')
  65 + user = create(:user, password: 'abcdefg', force_random_password: true)
  66 + user.password.should == '12345678'
  67 + end
60 68 end
61 69  
62   - it "should have authentication token" do
63   - user = Factory(:user)
64   - user.authentication_token.should_not == ""
  70 + describe 'authentication token' do
  71 + it "should have authentication token" do
  72 + user = Factory(:user)
  73 + user.authentication_token.should_not be_blank
  74 + end
65 75 end
66 76 end
... ...
spec/models/users_project_spec.rb
... ... @@ -10,7 +10,7 @@ describe UsersProject do
10 10 let!(:users_project) { create(:users_project) }
11 11  
12 12 it { should validate_presence_of(:user_id) }
13   - it { should validate_uniqueness_of(:user_id).scoped_to(:project_id) }
  13 + it { should validate_uniqueness_of(:user_id).scoped_to(:project_id).with_message(/already exists/) }
14 14  
15 15 it { should validate_presence_of(:project_id) }
16 16 end
... ...
spec/requests/api/projects_spec.rb
... ... @@ -27,38 +27,40 @@ describe Gitlab::API do
27 27  
28 28 describe "POST /projects" do
29 29 it "should create new project without code and path" do
30   - lambda {
31   - name = "foo"
32   - post api("/projects", user), {
33   - name: name
34   - }
35   - response.status.should == 201
36   - json_response["name"].should == name
37   - json_response["code"].should == name
38   - json_response["path"].should == name
39   - }.should change{Project.count}.by(1)
40   - end
41   - it "should create new project" do
42   - lambda {
43   - name = "foo"
44   - path = "bar"
45   - code = "bazz"
46   - post api("/projects", user), {
47   - code: code,
48   - path: path,
49   - name: name
50   - }
51   - response.status.should == 201
52   - json_response["name"].should == name
53   - json_response["path"].should == path
54   - json_response["code"].should == code
55   - }.should change{Project.count}.by(1)
56   - end
57   - it "should not create project without name" do
58   - lambda {
59   - post api("/projects", user)
60   - response.status.should == 404
61   - }.should_not change{Project.count}
  30 + expect { post api("/projects", user), name: 'foo' }.to change {Project.count}.by(1)
  31 + end
  32 +
  33 + it "should not create new project without name" do
  34 + expect { post api("/projects", user) }.to_not change {Project.count}
  35 + end
  36 +
  37 + it "should respond with 201 on success" do
  38 + post api("/projects", user), name: 'foo'
  39 + response.status.should == 201
  40 + end
  41 +
  42 + it "should repsond with 404 on failure" do
  43 + post api("/projects", user)
  44 + response.status.should == 404
  45 + end
  46 +
  47 + it "should assign attributes to project" do
  48 + project = Factory.attributes(:project, {
  49 + path: 'path',
  50 + code: 'code',
  51 + description: Faker::Lorem.sentence,
  52 + default_branch: 'stable',
  53 + issues_enabled: false,
  54 + wall_enabled: false,
  55 + merge_requests_enabled: false,
  56 + wiki_enabled: false
  57 + })
  58 +
  59 + post api("/projects", user), project
  60 +
  61 + project.each_pair do |k,v|
  62 + json_response[k.to_s].should == v
  63 + end
62 64 end
63 65 end
64 66  
... ...
spec/roles/repository_spec.rb 0 → 100644
... ... @@ -0,0 +1,72 @@
  1 +require 'spec_helper'
  2 +
  3 +describe Project, "Repository" do
  4 + let(:project) { build(:project) }
  5 +
  6 + describe "#empty_repo?" do
  7 + it "should return true if the repo doesn't exist" do
  8 + project.stub(repo_exists?: false, has_commits?: true)
  9 + project.should be_empty_repo
  10 + end
  11 +
  12 + it "should return true if the repo has commits" do
  13 + project.stub(repo_exists?: true, has_commits?: false)
  14 + project.should be_empty_repo
  15 + end
  16 +
  17 + it "should return false if the repo exists and has commits" do
  18 + project.stub(repo_exists?: true, has_commits?: true)
  19 + project.should_not be_empty_repo
  20 + end
  21 + end
  22 +
  23 + describe "#discover_default_branch" do
  24 + let(:master) { double(name: 'master') }
  25 + let(:stable) { double(name: 'stable') }
  26 +
  27 + it "returns 'master' when master exists" do
  28 + project.should_receive(:heads).and_return([stable, master])
  29 + project.discover_default_branch.should == 'master'
  30 + end
  31 +
  32 + it "returns non-master when master exists but default branch is set to something else" do
  33 + project.default_branch = 'stable'
  34 + project.should_receive(:heads).and_return([stable, master])
  35 + project.discover_default_branch.should == 'stable'
  36 + end
  37 +
  38 + it "returns a non-master branch when only one exists" do
  39 + project.should_receive(:heads).and_return([stable])
  40 + project.discover_default_branch.should == 'stable'
  41 + end
  42 +
  43 + it "returns nil when no branch exists" do
  44 + project.should_receive(:heads).and_return([])
  45 + project.discover_default_branch.should be_nil
  46 + end
  47 + end
  48 +
  49 + describe "#root_ref" do
  50 + it "returns default_branch when set" do
  51 + project.default_branch = 'stable'
  52 + project.root_ref.should == 'stable'
  53 + end
  54 +
  55 + it "returns 'master' when default_branch is nil" do
  56 + project.default_branch = nil
  57 + project.root_ref.should == 'master'
  58 + end
  59 + end
  60 +
  61 + describe "#root_ref?" do
  62 + it "returns true when branch is root_ref" do
  63 + project.default_branch = 'stable'
  64 + project.root_ref?('stable').should be_true
  65 + end
  66 +
  67 + it "returns false when branch is not root_ref" do
  68 + project.default_branch = nil
  69 + project.root_ref?('stable').should be_false
  70 + end
  71 + end
  72 +end
... ...
tmp/.gitkeep 0 → 100644