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
@@ -22,4 +22,4 @@ config/unicorn.rb @@ -22,4 +22,4 @@ config/unicorn.rb
22 db/data.yml 22 db/data.yml
23 .idea 23 .idea
24 .DS_Store 24 .DS_Store
25 - 25 +.chef
@@ -9,6 +9,8 @@ branches: @@ -9,6 +9,8 @@ branches:
9 - 'master' 9 - 'master'
10 rvm: 10 rvm:
11 - 1.9.3 11 - 1.9.3
  12 +services:
  13 + - mysql
12 before_script: 14 before_script:
13 - "cp config/database.yml.$DB config/database.yml" 15 - "cp config/database.yml.$DB config/database.yml"
14 - "cp config/gitlab.yml.example config/gitlab.yml" 16 - "cp config/gitlab.yml.example config/gitlab.yml"
@@ -323,7 +323,7 @@ GEM @@ -323,7 +323,7 @@ GEM
323 multi_json (~> 1.0) 323 multi_json (~> 1.0)
324 rubyzip 324 rubyzip
325 settingslogic (2.0.8) 325 settingslogic (2.0.8)
326 - shoulda-matchers (1.1.0) 326 + shoulda-matchers (1.3.0)
327 activesupport (>= 3.0.0) 327 activesupport (>= 3.0.0)
328 simplecov (0.6.4) 328 simplecov (0.6.4)
329 multi_json (~> 1.0) 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,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 @@ @@ -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,134 +17,3 @@
17 //= require raphael 17 //= require raphael
18 //= require branch-graph 18 //= require branch-graph
19 //= require_tree . 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,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 @@ @@ -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,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 @@ @@ -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 @@ @@ -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,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 @@ @@ -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,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 @@ @@ -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,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 * .main_box - for show pages 4 * .main_box - for show pages
5 * .ui-box - for simple block & widgets 5 * .ui-box - for simple block & widgets
6 * =================================== 6 * ===================================
app/assets/stylesheets/gitlab_bootstrap/buttons.scss
1 .btn { 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 border-color:#aaa; 3 border-color:#aaa;
7 &:hover { 4 &:hover {
8 @include bg-gray-gradient; 5 @include bg-gray-gradient;
@@ -12,10 +9,8 @@ @@ -12,10 +9,8 @@
12 9
13 &.primary { 10 &.primary {
14 background:#2a79A3; 11 background:#2a79A3;
  12 + @include bg-gradient(#47A7b7, #2585b5);
15 border-color: #2A79A3; 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 color:#fff; 14 color:#fff;
20 text-shadow: 0 1px 1px #268; 15 text-shadow: 0 1px 1px #268;
21 &:hover { 16 &:hover {
@@ -30,16 +25,11 @@ @@ -30,16 +25,11 @@
30 } 25 }
31 26
32 &.success { 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 &:hover { 30 &:hover {
41 - background: #6C6;  
42 - color: #fff; 31 + @extend .btn-success;
  32 + background: #51a351;
43 } 33 }
44 34
45 &.disabled { 35 &.disabled {
@@ -62,10 +52,8 @@ @@ -62,10 +52,8 @@
62 padding-right:30px; 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 border-color: #BD362F; 57 border-color: #BD362F;
70 58
71 &:hover { 59 &:hover {
app/assets/stylesheets/gitlab_bootstrap/files.scss
@@ -3,13 +3,13 @@ @@ -3,13 +3,13 @@
3 * 3 *
4 */ 4 */
5 .file_holder { 5 .file_holder {
6 - border:1px solid #CCC; 6 + border:1px solid #BBB;
7 margin-bottom:1em; 7 margin-bottom:1em;
8 @include solid_shade; 8 @include solid_shade;
9 9
10 .file_title { 10 .file_title {
11 border-bottom: 1px solid #bbb; 11 border-bottom: 1px solid #bbb;
12 - @include bg-gray-gradient; 12 + @include bg-dark-gray-gradient;
13 margin: 0; 13 margin: 0;
14 font-weight: normal; 14 font-weight: normal;
15 font-weight: bold; 15 font-weight: bold;
app/assets/stylesheets/highlight/white.scss
1 -table.highlighttable  
2 -{ 1 +table.highlighttable {
3 margin:0px; 2 margin:0px;
4 padding:0px; 3 padding:0px;
5 font-size:12px; 4 font-size:12px;
6 table-layout:fixed; 5 table-layout:fixed;
7 background: #EEE; 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 td.code, 19 td.code,
11 td.linenos{ 20 td.linenos{
12 padding:0; 21 padding:0;
app/assets/stylesheets/main.scss
1 @import "bootstrap"; 1 @import "bootstrap";
2 @import "bootstrap-responsive"; 2 @import "bootstrap-responsive";
3 3
4 -/** GITLAB colors **/ 4 +/** GitLab colors **/
5 $link_color:#3A89A3; 5 $link_color:#3A89A3;
6 $blue_link: #2fa0bb; 6 $blue_link: #2fa0bb;
7 $style_color: #474d57; 7 $style_color: #474d57;
8 $hover: #fdf5d9; 8 $hover: #fdf5d9;
9 9
10 -/** GITLAB Fonts **/ 10 +/** GitLab Fonts **/
11 @font-face { font-family: Korolev; src: url('korolev-medium-compressed.otf'); } 11 @font-face { font-family: Korolev; src: url('korolev-medium-compressed.otf'); }
12 12
13 /** MIXINS **/ 13 /** MIXINS **/
@@ -56,6 +56,13 @@ $hover: #fdf5d9; @@ -56,6 +56,13 @@ $hover: #fdf5d9;
56 border-radius: $radius; 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 @mixin bg-gray-gradient { 66 @mixin bg-gray-gradient {
60 background:#eee; 67 background:#eee;
61 background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf)); 68 background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #eee), to(#dfdfdf));
@@ -106,9 +113,9 @@ $hover: #fdf5d9; @@ -106,9 +113,9 @@ $hover: #fdf5d9;
106 @import "themes/ui_modern.scss"; 113 @import "themes/ui_modern.scss";
107 114
108 /** 115 /**
109 - * Gitlab bootstrap. 116 + * GitLab bootstrap.
110 * Overrides some styles of twitter bootstrap. 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 @import "gitlab_bootstrap/common.scss"; 120 @import "gitlab_bootstrap/common.scss";
114 @import "gitlab_bootstrap/typography.scss"; 121 @import "gitlab_bootstrap/typography.scss";
app/assets/stylesheets/sections/header.scss
@@ -22,7 +22,7 @@ header { @@ -22,7 +22,7 @@ header {
22 * 22 *
23 */ 23 */
24 .app_logo { 24 .app_logo {
25 - width:230px; 25 + width:200px;
26 float:left; 26 float:left;
27 position:relative; 27 position:relative;
28 top:-5px; 28 top:-5px;
@@ -31,7 +31,7 @@ header { @@ -31,7 +31,7 @@ header {
31 31
32 h1 { 32 h1 {
33 padding-top: 5px; 33 padding-top: 5px;
34 - width:102px; 34 + width:90px;
35 background: url('logo_dark.png') no-repeat 0px -3px; 35 background: url('logo_dark.png') no-repeat 0px -3px;
36 float:left; 36 float:left;
37 margin-left:5px; 37 margin-left:5px;
app/assets/stylesheets/sections/nav.scss
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 * Main Menu of Application 2 * Main Menu of Application
3 * 3 *
4 */ 4 */
5 -ul.main_menu { 5 +ul.main_menu {
6 border-radius: 4px; 6 border-radius: 4px;
7 margin: auto; 7 margin: auto;
8 margin:30px 0; 8 margin:30px 0;
@@ -12,7 +12,7 @@ ul.main_menu { @@ -12,7 +12,7 @@ ul.main_menu {
12 position:relative; 12 position:relative;
13 overflow:hidden; 13 overflow:hidden;
14 @include shade; 14 @include shade;
15 - .count { 15 + .count {
16 position: relative; 16 position: relative;
17 top: -1px; 17 top: -1px;
18 display: inline-block; 18 display: inline-block;
@@ -29,12 +29,12 @@ ul.main_menu { @@ -29,12 +29,12 @@ ul.main_menu {
29 border-radius: 8px; 29 border-radius: 8px;
30 -moz-border-radius: 8px; 30 -moz-border-radius: 8px;
31 } 31 }
32 - .label { 32 + .label {
33 background:$hover; 33 background:$hover;
34 text-shadow:none; 34 text-shadow:none;
35 color:$style_color; 35 color:$style_color;
36 } 36 }
37 - li { 37 + li {
38 list-style-type: none; 38 list-style-type: none;
39 margin: 0; 39 margin: 0;
40 display: table-cell; 40 display: table-cell;
@@ -43,7 +43,7 @@ ul.main_menu { @@ -43,7 +43,7 @@ ul.main_menu {
43 border-left: 1px solid #EEE; 43 border-left: 1px solid #EEE;
44 border-bottom:2px solid #CFCFCF; 44 border-bottom:2px solid #CFCFCF;
45 45
46 - &:first-child{ 46 + &:first-child{
47 -webkit-border-top-left-radius: 4px; 47 -webkit-border-top-left-radius: 4px;
48 -webkit-border-bottom-left-radius: 4px; 48 -webkit-border-bottom-left-radius: 4px;
49 -moz-border-radius-topleft: 4px; 49 -moz-border-radius-topleft: 4px;
@@ -53,31 +53,31 @@ ul.main_menu { @@ -53,31 +53,31 @@ ul.main_menu {
53 border-left: 0; 53 border-left: 0;
54 } 54 }
55 55
56 - &.current { 56 + &.current {
57 background-color:#D5D5D5; 57 background-color:#D5D5D5;
58 - border-bottom: 2px solid $style_color; 58 + border-bottom: 1px solid #AAA;
59 border-right: 1px solid #BBB; 59 border-right: 1px solid #BBB;
60 border-left: 1px solid #BBB; 60 border-left: 1px solid #BBB;
61 border-radius: 0 0 1px 1px; 61 border-radius: 0 0 1px 1px;
62 - &:first-child{ 62 + &:first-child{
63 border-bottom:none; 63 border-bottom:none;
64 border-left:none; 64 border-left:none;
65 } 65 }
66 } 66 }
67 67
68 - &.home {  
69 - a { 68 + &.home {
  69 + a {
70 background: url(home_icon.PNG) no-repeat center center; 70 background: url(home_icon.PNG) no-repeat center center;
71 text-indent:-9999px; 71 text-indent:-9999px;
72 min-width:20px; 72 min-width:20px;
73 - img { 73 + img {
74 position:relative; 74 position:relative;
75 top:4px; 75 top:4px;
76 } 76 }
77 } 77 }
78 } 78 }
79 } 79 }
80 - a { 80 + a {
81 display: block; 81 display: block;
82 text-align: center; 82 text-align: center;
83 font-weight:bold; 83 font-weight:bold;
app/assets/stylesheets/sections/projects.scss
@@ -75,17 +75,21 @@ @@ -75,17 +75,21 @@
75 padding: 4px 7px; 75 padding: 4px 7px;
76 border: 1px solid #CCC; 76 border: 1px solid #CCC;
77 margin-bottom:5px; 77 margin-bottom:5px;
78 - input[type=text] { 78 +}
  79 +
  80 +.project_clone_holder {
  81 + input[type="text"] {
79 border: 1px solid #BBB; 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 margin-top:50px; 89 margin-top:50px;
86 margin-bottom:50px; 90 margin-bottom:50px;
87 } 91 }
88 - h3 { 92 + h3 {
89 @extend .page_title; 93 @extend .page_title;
90 } 94 }
91 95
app/controllers/application_controller.rb
@@ -120,22 +120,12 @@ class ApplicationController &lt; ActionController::Base @@ -120,22 +120,12 @@ class ApplicationController &lt; ActionController::Base
120 end 120 end
121 end 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 def render_404 123 def render_404
134 render file: File.join(Rails.root, "public", "404"), layout: false, status: "404" 124 render file: File.join(Rails.root, "public", "404"), layout: false, status: "404"
135 end 125 end
136 126
137 def require_non_empty_project 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 end 129 end
140 130
141 def no_cache_headers 131 def no_cache_headers
app/controllers/commits_controller.rb
@@ -59,12 +59,19 @@ class CommitsController &lt; ApplicationController @@ -59,12 +59,19 @@ class CommitsController &lt; ApplicationController
59 59
60 def patch 60 def patch
61 @commit = project.commit(params[:id]) 61 @commit = project.commit(params[:id])
62 - 62 +
63 send_data( 63 send_data(
64 @commit.to_patch, 64 @commit.to_patch,
65 type: "text/plain", 65 type: "text/plain",
66 disposition: 'attachment', 66 disposition: 'attachment',
67 - filename: (@commit.id.to_s + ".patch") 67 + filename: "#{@commit.id.patch}"
68 ) 68 )
69 end 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 end 77 end
app/controllers/projects_controller.rb
@@ -50,7 +50,7 @@ class ProjectsController &lt; ApplicationController @@ -50,7 +50,7 @@ class ProjectsController &lt; ApplicationController
50 50
51 respond_to do |format| 51 respond_to do |format|
52 format.html do 52 format.html do
53 - if @project.repo_exists? && @project.has_commits? 53 + unless @project.empty_repo?
54 @last_push = current_user.recent_push(@project.id) 54 @last_push = current_user.recent_push(@project.id)
55 render :show 55 render :show
56 else 56 else
app/helpers/gitlab_markdown_helper.rb
1 module GitlabMarkdownHelper 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 # Use this in places where you would normally use link_to(gfm(...), ...). 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,18 +111,18 @@ class Notify &lt; ActionMailer::Base
111 # Examples 111 # Examples
112 # 112 #
113 # >> subject('Lorem ipsum') 113 # >> subject('Lorem ipsum')
114 - # => "gitlab | Lorem ipsum" 114 + # => "GitLab | Lorem ipsum"
115 # 115 #
116 # # Automatically inserts Project name when @project is set 116 # # Automatically inserts Project name when @project is set
117 # >> @project = Project.last 117 # >> @project = Project.last
118 # => #<Project id: 1, name: "Ruby on Rails", path: "ruby_on_rails", ...> 118 # => #<Project id: 1, name: "Ruby on Rails", path: "ruby_on_rails", ...>
119 # >> subject('Lorem ipsum') 119 # >> subject('Lorem ipsum')
120 - # => "gitlab | Lorem ipsum | Ruby on Rails" 120 + # => "GitLab | Lorem ipsum | Ruby on Rails"
121 # 121 #
122 # # Accepts multiple arguments 122 # # Accepts multiple arguments
123 # >> subject('Lorem ipsum', 'Dolor sit amet') 123 # >> subject('Lorem ipsum', 'Dolor sit amet')
124 - # => "gitlab | Lorem ipsum | Dolor sit amet" 124 + # => "GitLab | Lorem ipsum | Dolor sit amet"
125 def subject(*extra) 125 def subject(*extra)
126 - "gitlab | " << extra.join(' | ') << (@project ? " | #{@project.name}" : "") 126 + "GitLab | " << extra.join(' | ') << (@project ? " | #{@project.name}" : "")
127 end 127 end
128 end 128 end
app/models/note.rb
@@ -103,7 +103,7 @@ class Note &lt; ActiveRecord::Base @@ -103,7 +103,7 @@ class Note &lt; ActiveRecord::Base
103 # Returns true if this is an upvote note, 103 # Returns true if this is an upvote note,
104 # otherwise false is returned 104 # otherwise false is returned
105 def upvote? 105 def upvote?
106 - note =~ /^\+1/ ? true : false 106 + note.start_with?('+1') || note.start_with?(':+1:')
107 end 107 end
108 end 108 end
109 # == Schema Information 109 # == Schema Information
app/models/project.rb
@@ -104,6 +104,8 @@ class Project &lt; ActiveRecord::Base @@ -104,6 +104,8 @@ class Project &lt; ActiveRecord::Base
104 length: { within: 1..255 } 104 length: { within: 1..255 }
105 105
106 validates :owner, presence: true 106 validates :owner, presence: true
  107 + validates :issues_enabled, :wall_enabled, :merge_requests_enabled,
  108 + :wiki_enabled, inclusion: { in: [true, false] }
107 validate :check_limit 109 validate :check_limit
108 validate :repo_name 110 validate :repo_name
109 111
@@ -187,7 +189,7 @@ end @@ -187,7 +189,7 @@ end
187 # private_flag :boolean(1) default(TRUE), not null 189 # private_flag :boolean(1) default(TRUE), not null
188 # code :string(255) 190 # code :string(255)
189 # owner_id :integer(4) 191 # owner_id :integer(4)
190 -# default_branch :string(255) default("master"), not null 192 +# default_branch :string(255)
191 # issues_enabled :boolean(1) default(TRUE), not null 193 # issues_enabled :boolean(1) default(TRUE), not null
192 # wall_enabled :boolean(1) default(TRUE), not null 194 # wall_enabled :boolean(1) default(TRUE), not null
193 # merge_requests_enabled :boolean(1) default(TRUE), not null 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,7 +14,7 @@ class UsersProject &lt; ActiveRecord::Base
14 after_save :update_repository 14 after_save :update_repository
15 after_destroy :update_repository 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 validates_presence_of :user_id 18 validates_presence_of :user_id
19 validates_presence_of :project_id 19 validates_presence_of :project_id
20 20
@@ -48,10 +48,10 @@ class UsersProject &lt; ActiveRecord::Base @@ -48,10 +48,10 @@ class UsersProject &lt; ActiveRecord::Base
48 48
49 def self.access_roles 49 def self.access_roles
50 { 50 {
51 - "Guest" => GUEST,  
52 - "Reporter" => REPORTER, 51 + "Guest" => GUEST,
  52 + "Reporter" => REPORTER,
53 "Developer" => DEVELOPER, 53 "Developer" => DEVELOPER,
54 - "Master" => MASTER 54 + "Master" => MASTER
55 } 55 }
56 end 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 def identifier 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 end 11 end
5 12
6 def is_admin? 13 def is_admin?
app/roles/issue_commonality.rb
@@ -16,7 +16,7 @@ module IssueCommonality @@ -16,7 +16,7 @@ module IssueCommonality
16 validates :title, 16 validates :title,
17 presence: true, 17 presence: true,
18 length: { within: 0..255 } 18 length: { within: 0..255 }
19 - 19 + validates :closed, inclusion: { in: [true, false] }
20 20
21 scope :opened, where(closed: false) 21 scope :opened, where(closed: false)
22 scope :closed, where(closed: true) 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 module PushObserver 4 module PushObserver
2 def observe_push(oldrev, newrev, ref, user) 5 def observe_push(oldrev, newrev, ref, user)
3 data = post_receive_data(oldrev, newrev, ref, user) 6 data = post_receive_data(oldrev, newrev, ref, user)
@@ -84,11 +87,10 @@ module PushObserver @@ -84,11 +87,10 @@ module PushObserver
84 data 87 data
85 end 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 def trigger_post_receive(oldrev, newrev, ref, user) 94 def trigger_post_receive(oldrev, newrev, ref, user)
93 # Create push event 95 # Create push event
94 self.observe_push(oldrev, newrev, ref, user) 96 self.observe_push(oldrev, newrev, ref, user)
@@ -101,5 +103,11 @@ module PushObserver @@ -101,5 +103,11 @@ module PushObserver
101 103
102 # Create satellite 104 # Create satellite
103 self.satellite.create unless self.satellite.exists? 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 end 112 end
105 end 113 end
app/roles/repository.rb
@@ -8,6 +8,10 @@ module Repository @@ -8,6 +8,10 @@ module Repository
8 false 8 false
9 end 9 end
10 10
  11 + def empty_repo?
  12 + !repo_exists? || !has_commits?
  13 + end
  14 +
11 def commit(commit_id = nil) 15 def commit(commit_id = nil)
12 Commit.find_or_first(repo, commit_id, root_ref) 16 Commit.find_or_first(repo, commit_id, root_ref)
13 end 17 end
@@ -38,7 +42,7 @@ module Repository @@ -38,7 +42,7 @@ module Repository
38 42
39 def has_post_receive_file? 43 def has_post_receive_file?
40 hook_file = File.join(path_to_repo, 'hooks', 'post-receive') 44 hook_file = File.join(path_to_repo, 'hooks', 'post-receive')
41 - File.exists?(hook_file) 45 + File.exists?(hook_file)
42 end 46 end
43 47
44 def tags 48 def tags
@@ -67,7 +71,7 @@ module Repository @@ -67,7 +71,7 @@ module Repository
67 71
68 def repo_exists? 72 def repo_exists?
69 @repo_exists ||= (repo && !repo.branches.empty?) 73 @repo_exists ||= (repo && !repo.branches.empty?)
70 - rescue 74 + rescue
71 @repo_exists = false 75 @repo_exists = false
72 end 76 end
73 77
@@ -90,24 +94,42 @@ module Repository @@ -90,24 +94,42 @@ module Repository
90 end.sort_by(&:name) 94 end.sort_by(&:name)
91 end 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 def has_commits? 115 def has_commits?
94 !!commit 116 !!commit
95 end 117 end
96 118
97 - def root_ref 119 + def root_ref
98 default_branch || "master" 120 default_branch || "master"
99 end 121 end
100 122
101 - def root_ref? branch 123 + def root_ref?(branch)
102 root_ref == branch 124 root_ref == branch
103 end 125 end
104 126
105 # Archive Project to .tar.gz 127 # Archive Project to .tar.gz
106 # 128 #
107 - # Already packed repo archives stored at 129 + # Already packed repo archives stored at
108 # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz 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 ref = ref || self.root_ref 133 ref = ref || self.root_ref
112 commit = self.commit(ref) 134 commit = self.commit(ref)
113 return nil unless commit 135 return nil unless commit
@@ -134,6 +156,6 @@ module Repository @@ -134,6 +156,6 @@ module Repository
134 end 156 end
135 157
136 def http_url_to_repo 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 end 160 end
139 end 161 end
app/views/deploy_keys/_form.html.haml
@@ -11,8 +11,13 @@ @@ -11,8 +11,13 @@
11 .input= f.text_field :title 11 .input= f.text_field :title
12 .clearfix 12 .clearfix
13 = f.label :key 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 .actions 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 = render "repositories/head" 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 = link_to new_project_deploy_key_path(@project), class: "btn small", title: "New Deploy Key" do 7 = link_to new_project_deploy_key_path(@project), class: "btn small", title: "New Deploy Key" do
6 Add Deploy Key 8 Add Deploy Key
7 -  
8 - if @keys.any? 9 - if @keys.any?
9 %table 10 %table
  11 + %thead
  12 + %tr
  13 + %th Keys
  14 + %th
  15 + %th
10 - @keys.each do |key| 16 - @keys.each do |key|
11 = render(partial: 'show', locals: {key: key}) 17 = render(partial: 'show', locals: {key: key})
app/views/deploy_keys/new.html.haml
1 = render "repositories/head" 1 = render "repositories/head"
2 2
3 -%h3 New Deploy key 3 +%h3.page_title New Deploy key
4 %hr 4 %hr
5 5
6 = render 'form' 6 = render 'form'
app/views/deploy_keys/show.html.haml
1 = render "repositories/head" 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 %hr 11 %hr
4 %pre= @key.key 12 %pre= @key.key
5 -.actions 13 +.right
6 = link_to 'Remove', project_deploy_key_path(@key.project, @key), confirm: 'Are you sure?', method: :delete, class: "danger btn delete-key" 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 %h1 Git Error 1 %h1 Git Error
2 %hr 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 .git_error_tips 5 .git_error_tips
6 %h4 Tips for Administrator: 6 %h4 Tips for Administrator:
app/views/help/api.html.haml
@@ -15,6 +15,8 @@ @@ -15,6 +15,8 @@
15 %a{href: "#users"} Users 15 %a{href: "#users"} Users
16 %li 16 %li
17 %a{href: "#issues"} Issues 17 %a{href: "#issues"} Issues
  18 + %li
  19 + %a{href: "#milestones"} Milestones
18 20
19 .file_holder#README 21 .file_holder#README
20 .file_title 22 .file_title
app/views/help/index.html.haml
@@ -30,7 +30,7 @@ @@ -30,7 +30,7 @@
30 %h5= link_to "API", help_api_path 30 %h5= link_to "API", help_api_path
31 31
32 %li 32 %li
33 - %h5= link_to "Gitlab Markdown", help_markdown_path 33 + %h5= link_to "GitLab Markdown", help_markdown_path
34 34
35 %li 35 %li
36 %h5= link_to "SSH keys", help_ssh_path 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 .back_link 2 .back_link
3 = link_to help_path do 3 = link_to help_path do
4 &larr; to index 4 &larr; to index
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 .row 7 .row
8 .span8 8 .span8
9 %p 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 It extends the standard Markdown in a few significant ways adds some useful functionality. 11 It extends the standard Markdown in a few significant ways adds some useful functionality.
12 12
13 %p You can use GFM in: 13 %p You can use GFM in:
@@ -62,7 +62,7 @@ @@ -62,7 +62,7 @@
62 %p becomes 62 %p becomes
63 = markdown %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```} 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 %p 67 %p
68 GFM recognizes special references. 68 GFM recognizes special references.
@@ -90,12 +90,11 @@ @@ -90,12 +90,11 @@
90 -# this example will only be shown if the user has a project with at least one issue 90 -# this example will only be shown if the user has a project with at least one issue
91 - if @project = current_user.projects.first 91 - if @project = current_user.projects.first
92 - if issue = @project.issues.first 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 %pre= "This is related to ##{issue.id}. @#{current_user.name} is working on solving it." 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 .span4.right 99 .span4.right
101 .alert.alert-info 100 .alert.alert-info
app/views/help/ssh.html.haml
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 %hr 5 %hr
6 6
7 %p.slead 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 %p.slead 10 %p.slead
11 To generate a new SSH key just open your terminal and use code below. 11 To generate a new SSH key just open your terminal and use code below.
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 \# Generating public/private rsa key pair... 17 \# Generating public/private rsa key pair...
18 18
19 %p.slead 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 %pre.dark 22 %pre.dark
23 cat ~/.ssh/id_rsa.pub 23 cat ~/.ssh/id_rsa.pub
app/views/help/system_hooks.html.haml
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 %hr 5 %hr
6 6
7 %p.slead 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 %br 9 %br
10 System Hooks can be used for logging or change information in LDAP server. 10 System Hooks can be used for logging or change information in LDAP server.
11 %br 11 %br
app/views/help/web_hooks.html.haml
@@ -5,11 +5,11 @@ @@ -5,11 +5,11 @@
5 %hr 5 %hr
6 6
7 %p.slead 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 %br 9 %br
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. 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 %br 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 %h5 Hooks request example: 13 %h5 Hooks request example:
14 = render "hooks/data_ex" 14 = render "hooks/data_ex"
15 15
app/views/help/workflow.html.haml
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 git commit -am "My feature is ready" 24 git commit -am "My feature is ready"
25 25
26 %li 26 %li
27 - %p Push your branch to gitlabhq 27 + %p Push your branch to GitLab
28 .bash 28 .bash
29 %pre.dark 29 %pre.dark
30 git push origin $feature_name 30 git push origin $feature_name
app/views/hooks/_data_ex.html.erb
@@ -32,7 +32,7 @@ @@ -32,7 +32,7 @@
32 :timestamp => "2012-01-03T23:36:29+02:00", 32 :timestamp => "2012-01-03T23:36:29+02:00",
33 :url => "http://localhost/diaspora/commits/da1560886d...", 33 :url => "http://localhost/diaspora/commits/da1560886d...",
34 :author => { 34 :author => {
35 - :name => "gitlab dev user", 35 + :name => "GitLab dev user",
36 :email => "gitlabdev@dv6700.(none)" 36 :email => "gitlabdev@dv6700.(none)"
37 } 37 }
38 } 38 }
app/views/issues/_form.html.haml
@@ -38,7 +38,7 @@ @@ -38,7 +38,7 @@
38 = f.label :description, "Details" 38 = f.label :description, "Details"
39 .input 39 .input
40 = f.text_area :description, maxlength: 2000, class: "xxlarge", rows: 14 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 .actions 44 .actions
app/views/keys/index.html.haml
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 4
5 %hr 5 %hr
6 %p.slead 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 %table#keys-table 10 %table#keys-table
app/views/keys/show.html.haml
@@ -10,5 +10,5 @@ @@ -10,5 +10,5 @@
10 %hr 10 %hr
11 11
12 %pre= @key.key 12 %pre= @key.key
13 -.actions 13 +.right
14 = link_to 'Remove', @key, confirm: 'Are you sure?', method: :delete, class: "btn danger delete-key" 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,7 +2,7 @@
2 %head 2 %head
3 %meta{content: "text/html; charset=utf-8", "http-equiv" => "Content-Type"} 3 %meta{content: "text/html; charset=utf-8", "http-equiv" => "Content-Type"}
4 %title 4 %title
5 - gitlabhq 5 + GitLab
6 :css 6 :css
7 .header h1 {color: #BBBBBB !important; font: bold 32px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 40px;} 7 .header h1 {color: #BBBBBB !important; font: bold 32px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 40px;}
8 .header p {color: #c6c6c6; font: normal 12px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 18px;} 8 .header p {color: #c6c6c6; font: normal 12px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 18px;}
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 21
22 %td{align: "left", style: "padding: 18px 0 10px;", width: "580"} 22 %td{align: "left", style: "padding: 18px 0 10px;", width: "580"}
23 %h1{style: "color: #BBBBBB; font: normal 32px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 40px;"} 23 %h1{style: "color: #BBBBBB; font: normal 32px Helvetica, Arial, sans-serif; margin: 0; padding: 0; line-height: 40px;"}
24 - gitlab 24 + GITLAB
25 - if @project 25 - if @project
26 | #{@project.name} 26 | #{@project.name}
27 %table{align: "center", bgcolor: "#fff", border: "0", cellpadding: "0", cellspacing: "0", style: "font-family: Helvetica, Arial, sans-serif; background: #fff;", width: "600"} 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,7 +22,7 @@
22 = f.label :description, "Description", class: "control-label" 22 = f.label :description, "Description", class: "control-label"
23 .controls 23 .controls
24 = f.text_area :description, maxlength: 2000, class: "input-xlarge", rows: 10 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 .span6 26 .span6
27 .control-group 27 .control-group
28 = f.label :due_date, "Due Date", class: "control-label" 28 = f.label :due_date, "Due Date", class: "control-label"
app/views/notes/_form.html.haml
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 = f.text_area :note, size: 255, class: 'note-text' 11 = f.text_area :note, size: 255, class: 'note-text'
12 #preview-note.preview_note.hide 12 #preview-note.preview_note.hide
13 .hint 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 .clearfix 15 .clearfix
16 16
17 .row.note_advanced_opts.hide 17 .row.note_advanced_opts.hide
app/views/notify/new_user_email.html.haml
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 %h2{style: "color:#646464; font-weight: bold; margin: 0; padding: 0; line-height: 26px; font-size: 18px; font-family: Helvetica, Arial, sans-serif; "} 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 Hi #{@user['name']}! 7 Hi #{@user['name']}!
8 %p{style: "color:#767676; font-weight: normal; margin: 0; padding: 0; line-height: 20px; font-size: 12px;font-family: Helvetica, Arial, sans-serif; "} 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 %td{style: "font-size: 1px; line-height: 1px;", width: "21"} 10 %td{style: "font-size: 1px; line-height: 1px;", width: "21"}
11 %tr 11 %tr
12 %td{style: "font-size: 1px; line-height: 1px;", width: "21"} 12 %td{style: "font-size: 1px; line-height: 1px;", width: "21"}
app/views/projects/_clone_panel.html.haml
@@ -3,19 +3,19 @@ @@ -3,19 +3,19 @@
3 .span7 3 .span7
4 .form-horizontal 4 .form-horizontal
5 .input-prepend.project_clone_holder 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 = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5" 8 = text_field_tag :project_clone, @project.url_to_repo, class: "one_click_select span5"
9 .span4.right 9 .span4.right
10 .right 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,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 = render 'shared/no_ssh' 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 %div.git-empty 4 %div.git-empty
11 %h4 Git global setup: 5 %h4 Git global setup:
12 %pre.dark 6 %pre.dark
@@ -36,16 +30,3 @@ @@ -36,16 +30,3 @@
36 - if can? current_user, :admin_project, @project 30 - if can? current_user, :admin_project, @project
37 .prepend-top-20 31 .prepend-top-20
38 = link_to 'Remove project', @project, confirm: 'Are you sure?', method: :delete, class: "btn danger right" 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,13 +2,3 @@
2 = render 'clone_panel' 2 = render 'clone_panel'
3 = render "events/event_last_push", event: @last_push 3 = render "events/event_last_push", event: @last_push
4 .content_list= render @events 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,4 +7,8 @@
7 %li{class: "#{'active' if (controller.controller_name == "refs") }"} 7 %li{class: "#{'active' if (controller.controller_name == "refs") }"}
8 = link_to tree_project_ref_path(@project, @ref) do 8 = link_to tree_project_ref_path(@project, @ref) do
9 Source 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,5 +6,5 @@
6 6
7 // Load last commit log for each file in tree 7 // Load last commit log for each file in tree
8 $('#tree-slider').waitForImages(function() { 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,7 +3,7 @@
3 3
4 .team_member_show 4 .team_member_show
5 - if can? current_user, :admin_project, @project 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 .profile_avatar_holder 7 .profile_avatar_holder
8 = image_tag gravatar_icon(user.email, 60), class: "borders" 8 = image_tag gravatar_icon(user.email, 60), class: "borders"
9 %h3 9 %h3
app/views/wikis/_form.html.haml
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 .middle_box_content 14 .middle_box_content
15 .input 15 .input
16 %span.cgray 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 To link to a (new) page you can just type 18 To link to a (new) page you can just type
19 %code [Link Title](page-slug) 19 %code [Link Title](page-slug)
20 \. 20 \.
config/routes.rb
@@ -50,10 +50,6 @@ Gitlab::Application.routes.draw do @@ -50,10 +50,6 @@ Gitlab::Application.routes.draw do
50 end 50 end
51 end 51 end
52 resources :team_members, :only => [:edit, :update, :destroy] 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 resources :hooks, :only => [:index, :create, :destroy] do 53 resources :hooks, :only => [:index, :create, :destroy] do
58 get :test 54 get :test
59 end 55 end
db/migrate/20120905043334_set_default_branch_default_to_nil.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -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
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 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 create_table "events", :force => true do |t| 16 create_table "events", :force => true do |t|
17 t.string "target_type" 17 t.string "target_type"
@@ -98,16 +98,16 @@ ActiveRecord::Schema.define(:version =&gt; 20120729131232) do @@ -98,16 +98,16 @@ ActiveRecord::Schema.define(:version =&gt; 20120729131232) do
98 t.string "name" 98 t.string "name"
99 t.string "path" 99 t.string "path"
100 t.text "description" 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 t.string "code" 104 t.string "code"
105 t.integer "owner_id" 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 end 111 end
112 112
113 create_table "protected_branches", :force => true do |t| 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 ```json 7 ```json
10 { 8 {
@@ -12,10 +10,9 @@ If no or invalid `private_token` provided error message will be returned with st @@ -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 GET http://example.com/api/v2/projects?private_token=QVy1PB7sTxfy4pqfZM1U 18 GET http://example.com/api/v2/projects?private_token=QVy1PB7sTxfy4pqfZM1U
doc/api/projects.md
1 ## List projects 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 GET /projects 6 GET /projects
@@ -55,7 +55,7 @@ GET /projects @@ -55,7 +55,7 @@ GET /projects
55 55
56 ## Single project 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 GET /projects/:id 61 GET /projects/:id
@@ -102,6 +102,12 @@ Parameters: @@ -102,6 +102,12 @@ Parameters:
102 + `name` (required) - new project name 102 + `name` (required) - new project name
103 + `code` (optional) - new project code, uses project name if not set 103 + `code` (optional) - new project code, uses project name if not set
104 + `path` (optional) - new project path, uses project name if not set 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 Will return created project with status `201 Created` on success, or `404 Not 112 Will return created project with status `201 Created` on success, or `404 Not
107 found` on fail. 113 found` on fail.
@@ -109,7 +115,7 @@ found` on fail. @@ -109,7 +115,7 @@ found` on fail.
109 115
110 ## Project repository branches 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 GET /projects/:id/repository/branches 121 GET /projects/:id/repository/branches
@@ -186,7 +192,7 @@ Parameters: @@ -186,7 +192,7 @@ Parameters:
186 192
187 ## Project repository tags 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 GET /projects/:id/repository/tags 198 GET /projects/:id/repository/tags
@@ -237,3 +243,4 @@ Parameters: @@ -237,3 +243,4 @@ Parameters:
237 + `filepath` (required) - The path the file 243 + `filepath` (required) - The path the file
238 244
239 Will return the raw file contents. 245 Will return the raw file contents.
  246 +
doc/debian_ubuntu.sh
@@ -1,45 +0,0 @@ @@ -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,7 +20,7 @@ You might have some luck using these, but no guarantees:
20 - MacOS X 20 - MacOS X
21 - FreeBSD 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 ## This installation guide created for Debian/Ubuntu and properly tested. 25 ## This installation guide created for Debian/Ubuntu and properly tested.
26 26
@@ -28,40 +28,44 @@ The installation consists of 6 steps: @@ -28,40 +28,44 @@ The installation consists of 6 steps:
28 28
29 1. Install packages / dependencies 29 1. Install packages / dependencies
30 2. Install ruby 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 5. Start the web front-end 33 5. Start the web front-end
34 6. Start a Resque worker (for background processing) 34 6. Start a Resque worker (for background processing)
35 35
36 ### IMPORTANT 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 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. 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 > # Install curl and sudo 47 > # Install curl and sudo
48 > apt-get install curl sudo 48 > apt-get install curl sudo
49 > 49 >
50 > # 3 steps in 1 command :) 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 # 1. Install packages 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 sudo apt-get update 70 sudo apt-get update
67 sudo apt-get upgrade 71 sudo apt-get upgrade
@@ -71,16 +75,16 @@ Also read the [Read this before you submit an issue](https://github.com/gitlabhq @@ -71,16 +75,16 @@ Also read the [Read this before you submit an issue](https://github.com/gitlabhq
71 # If you want to use MySQL: 75 # If you want to use MySQL:
72 sudo apt-get install -y mysql-server mysql-client libmysqlclient-dev 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 ./configure 83 ./configure
80 make 84 make
81 sudo make install 85 sudo make install
82 86
83 -# 3. Install gitolite 87 +# 3. Install Gitolite
84 88
85 Create user for git: 89 Create user for git:
86 90
@@ -93,12 +97,12 @@ Create user for git: @@ -93,12 +97,12 @@ Create user for git:
93 --home /home/git \ 97 --home /home/git \
94 git 98 git
95 99
96 -Create user for gitlab: 100 +Create user for GitLab:
97 101
98 # ubuntu/debian 102 # ubuntu/debian
99 sudo adduser --disabled-login --gecos 'gitlab system' gitlab 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 sudo usermod -a -G git gitlab 107 sudo usermod -a -G git gitlab
104 108
@@ -106,10 +110,10 @@ Generate key: @@ -106,10 +110,10 @@ Generate key:
106 110
107 sudo -H -u gitlab ssh-keygen -q -N '' -t rsa -f /home/gitlab/.ssh/id_rsa 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 cd /home/git 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 Setup: 118 Setup:
115 119
@@ -135,23 +139,23 @@ Permissions: @@ -135,23 +139,23 @@ Permissions:
135 # if succeed you can remove it 139 # if succeed you can remove it
136 sudo rm -rf /tmp/gitolite-admin 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 sudo gem install charlock_holmes --version '0.6.8' 148 sudo gem install charlock_holmes --version '0.6.8'
143 sudo pip install pygments 149 sudo pip install pygments
144 sudo gem install bundler 150 sudo gem install bundler
145 cd /home/gitlab 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 cd gitlab 153 cd gitlab
148 154
149 - sudo -u gitlab mkdir tmp  
150 -  
151 # Rename config files 155 # Rename config files
152 sudo -u gitlab cp config/gitlab.yml.example config/gitlab.yml 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 # SQLite 160 # SQLite
157 sudo -u gitlab cp config/database.yml.sqlite config/database.yml 161 sudo -u gitlab cp config/database.yml.sqlite config/database.yml
@@ -163,7 +167,7 @@ Permissions: @@ -163,7 +167,7 @@ Permissions:
163 # Login to MySQL 167 # Login to MySQL
164 $ mysql -u root -p 168 $ mysql -u root -p
165 169
166 - # Create the gitlabhq production database 170 + # Create the GitLab production database
167 mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`; 171 mysql> CREATE DATABASE IF NOT EXISTS `gitlabhq_production` DEFAULT CHARACTER SET `utf8` COLLATE `utf8_unicode_ci`;
168 172
169 # Create the MySQL User change $password to a real password 173 # Create the MySQL User change $password to a real password
@@ -179,15 +183,17 @@ Permissions: @@ -179,15 +183,17 @@ Permissions:
179 183
180 sudo -u gitlab -H bundle install --without development test --deployment 184 sudo -u gitlab -H bundle install --without development test --deployment
181 185
182 -#### Setup DB 186 +#### Setup database
183 187
184 sudo -u gitlab bundle exec rake gitlab:app:setup RAILS_ENV=production 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 sudo cp ./lib/hooks/post-receive /home/git/share/gitolite/hooks/common/post-receive 192 sudo cp ./lib/hooks/post-receive /home/git/share/gitolite/hooks/common/post-receive
189 sudo chown git:git /home/git/share/gitolite/hooks/common/post-receive 193 sudo chown git:git /home/git/share/gitolite/hooks/common/post-receive
190 194
  195 +#### Check application status
  196 +
191 Checking status: 197 Checking status:
192 198
193 sudo -u gitlab bundle exec rake gitlab:app:status RAILS_ENV=production 199 sudo -u gitlab bundle exec rake gitlab:app:status RAILS_ENV=production
@@ -208,9 +214,9 @@ Checking status: @@ -208,9 +214,9 @@ Checking status:
208 UMASK for .gitolite.rc is 0007? ............YES 214 UMASK for .gitolite.rc is 0007? ............YES
209 /home/git/share/gitolite/hooks/common/post-receive exists? ............YES 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 Application can be started with next command: 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,12 +231,12 @@ You can login via web using admin generated with setup:
225 admin@local.host 231 admin@local.host
226 5iveL!fe 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 # Manually 236 # Manually
231 sudo -u gitlab bundle exec rake environment resque:work QUEUE=* RAILS_ENV=production BACKGROUND=yes 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 sudo -u gitlab ./resque.sh 240 sudo -u gitlab ./resque.sh
235 # if you run this as root /home/gitlab/gitlab/tmp/pids/resque_worker.pid will be owned by root 241 # if you run this as root /home/gitlab/gitlab/tmp/pids/resque_worker.pid will be owned by root
236 # causing the resque worker not to start via init script on next boot/service restart 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,19 +246,19 @@ You can login via web using admin generated with setup:
240 246
241 # Nginx && Unicorn 247 # Nginx && Unicorn
242 248
243 -### Install Nginx  
244 -  
245 - sudo apt-get install nginx  
246 -  
247 -## Unicorn 249 +## 1. Unicorn
248 250
249 cd /home/gitlab/gitlab 251 cd /home/gitlab/gitlab
250 sudo -u gitlab cp config/unicorn.rb.orig config/unicorn.rb 252 sudo -u gitlab cp config/unicorn.rb.orig config/unicorn.rb
251 sudo -u gitlab bundle exec unicorn_rails -c config/unicorn.rb -E production -D 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 sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab 262 sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab
257 263
258 # Change **YOUR_SERVER_IP** and **YOUR_SERVER_FQDN** 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,22 +266,21 @@ Add gitlab to nginx sites &amp; change with your host specific settings
260 # of the host serving GitLab. 266 # of the host serving GitLab.
261 sudo vim /etc/nginx/sites-enabled/gitlab 267 sudo vim /etc/nginx/sites-enabled/gitlab
262 268
263 -Restart nginx:  
264 269
  270 + # Restart nginx:
265 /etc/init.d/nginx restart 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 sudo chmod +x /etc/init.d/gitlab 278 sudo chmod +x /etc/init.d/gitlab
274 279
275 -Gitlab autostart: 280 +GitLab autostart:
276 281
277 sudo update-rc.d gitlab defaults 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 sudo /etc/init.d/gitlab restart 286 sudo /etc/init.d/gitlab restart
features/projects/issues/issues.feature
@@ -4,7 +4,7 @@ Feature: Issues @@ -4,7 +4,7 @@ Feature: Issues
4 And I own project "Shop" 4 And I own project "Shop"
5 And project "Shop" have "Release 0.4" open issue 5 And project "Shop" have "Release 0.4" open issue
6 And project "Shop" have "Release 0.3" closed issue 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 Scenario: I should see open issues 9 Scenario: I should see open issues
10 Given I should see "Release 0.4" in issues 10 Given I should see "Release 0.4" in issues
@@ -36,3 +36,31 @@ Feature: Issues @@ -36,3 +36,31 @@ Feature: Issues
36 Given I visit issue page "Release 0.4" 36 Given I visit issue page "Release 0.4"
37 And I leave a comment like "XML attached" 37 And I leave a comment like "XML attached"
38 Then I should see comment "XML attached" 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 @@ @@ -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 Then /^I should see "(.*?)" link$/ do |arg1| 1 Then /^I should see "(.*?)" link$/ do |arg1|
6 page.should have_link(arg1) 2 page.should have_link(arg1)
7 end 3 end
@@ -51,10 +47,10 @@ Then /^I click &quot;(.*?)&quot; link$/ do |arg1| @@ -51,10 +47,10 @@ Then /^I click &quot;(.*?)&quot; link$/ do |arg1|
51 end 47 end
52 48
53 Then /^I see prefilled new Merge Request page$/ do 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 end 54 end
59 55
60 Given /^I visit dashboard search page$/ do 56 Given /^I visit dashboard search page$/ do
@@ -66,10 +62,6 @@ Given /^I search for &quot;(.*?)&quot;$/ do |arg1| @@ -66,10 +62,6 @@ Given /^I search for &quot;(.*?)&quot;$/ do |arg1|
66 click_button "Search" 62 click_button "Search"
67 end 63 end
68 64
69 -Given /^I visit dashboard issues page$/ do  
70 - visit dashboard_issues_path  
71 -end  
72 -  
73 Then /^I should see issues assigned to me$/ do 65 Then /^I should see issues assigned to me$/ do
74 issues = @user.issues 66 issues = @user.issues
75 issues.each do |issue| 67 issues.each do |issue|
@@ -78,10 +70,6 @@ Then /^I should see issues assigned to me$/ do @@ -78,10 +70,6 @@ Then /^I should see issues assigned to me$/ do
78 end 70 end
79 end 71 end
80 72
81 -Given /^I visit dashboard merge requests page$/ do  
82 - visit dashboard_merge_requests_path  
83 -end  
84 -  
85 Then /^I should see my merge requests$/ do 73 Then /^I should see my merge requests$/ do
86 merge_requests = @user.merge_requests 74 merge_requests = @user.merge_requests
87 merge_requests.each do |mr| 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 Then /^I should see my profile info$/ do 1 Then /^I should see my profile info$/ do
6 page.should have_content "Profile" 2 page.should have_content "Profile"
7 page.should have_content @user.name 3 page.should have_content @user.name
8 page.should have_content @user.email 4 page.should have_content @user.email
9 end 5 end
10 6
11 -Given /^I visit profile password page$/ do  
12 - visit profile_password_path  
13 -end  
14 -  
15 Then /^I change my password$/ do 7 Then /^I change my password$/ do
16 fill_in "user_password", :with => "222333" 8 fill_in "user_password", :with => "222333"
17 fill_in "user_password_confirmation", :with => "222333" 9 fill_in "user_password_confirmation", :with => "222333"
@@ -22,10 +14,6 @@ Then /^I should be redirected to sign in page$/ do @@ -22,10 +14,6 @@ Then /^I should be redirected to sign in page$/ do
22 current_path.should == new_user_session_path 14 current_path.should == new_user_session_path
23 end 15 end
24 16
25 -Given /^I visit profile token page$/ do  
26 - visit profile_token_path  
27 -end  
28 -  
29 Then /^I reset my token$/ do 17 Then /^I reset my token$/ do
30 @old_token = @user.private_token 18 @old_token = @user.private_token
31 click_button "Reset" 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 Then /^I should see files from repository$/ do 1 Then /^I should see files from repository$/ do
6 page.should have_content("app") 2 page.should have_content("app")
7 page.should have_content("History") 3 page.should have_content("History")
8 page.should have_content("Gemfile") 4 page.should have_content("Gemfile")
9 end 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 Then /^I should see files from repository for "(.*?)"$/ do |arg1| 7 Then /^I should see files from repository for "(.*?)"$/ do |arg1|
16 current_path.should == tree_project_ref_path(@project, arg1) 8 current_path.should == tree_project_ref_path(@project, arg1)
17 page.should have_content("app") 9 page.should have_content("app")
@@ -31,10 +23,6 @@ Given /^I click on raw button$/ do @@ -31,10 +23,6 @@ Given /^I click on raw button$/ do
31 click_link "raw" 23 click_link "raw"
32 end 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 Then /^I should see raw file content$/ do 26 Then /^I should see raw file content$/ do
39 page.source.should == ValidCommit::BLOB_FILE 27 page.source.should == ValidCommit::BLOB_FILE
40 end 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 Then /^I see project commits$/ do 1 Then /^I see project commits$/ do
6 current_path.should == project_commits_path(@project) 2 current_path.should == project_commits_path(@project)
7 3
@@ -23,19 +19,11 @@ Then /^I see commits atom feed$/ do @@ -23,19 +19,11 @@ Then /^I see commits atom feed$/ do
23 page.body.should have_selector("entry summary", :text => commit.description) 19 page.body.should have_selector("entry summary", :text => commit.description)
24 end 20 end
25 21
26 -Given /^I click on commit link$/ do  
27 - visit project_commit_path(@project, ValidCommit::ID)  
28 -end  
29 -  
30 Then /^I see commit info$/ do 22 Then /^I see commit info$/ do
31 page.should have_content ValidCommit::MESSAGE 23 page.should have_content ValidCommit::MESSAGE
32 page.should have_content "Showing 1 changed file" 24 page.should have_content "Showing 1 changed file"
33 end 25 end
34 26
35 -Given /^I visit compare refs page$/ do  
36 - visit compare_project_commits_path(@project)  
37 -end  
38 -  
39 Given /^I fill compare fields with refs$/ do 27 Given /^I fill compare fields with refs$/ do
40 fill_in "from", :with => "master" 28 fill_in "from", :with => "master"
41 fill_in "to", :with => "stable" 29 fill_in "to", :with => "stable"
@@ -48,18 +36,6 @@ Given /^I see compared refs$/ do @@ -48,18 +36,6 @@ Given /^I see compared refs$/ do
48 page.should have_content "Showing 73 changed files" 36 page.should have_content "Showing 73 changed files"
49 end 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 Then /^I should see "(.*?)" recent branches list$/ do |arg1| 39 Then /^I should see "(.*?)" recent branches list$/ do |arg1|
64 page.should have_content("Branches") 40 page.should have_content("Branches")
65 page.should have_content("master") 41 page.should have_content("master")
@@ -76,7 +52,7 @@ Then /^I should see &quot;(.*?)&quot; all tags list$/ do |arg1| @@ -76,7 +52,7 @@ Then /^I should see &quot;(.*?)&quot; all tags list$/ do |arg1|
76 end 52 end
77 53
78 Then /^I should see "(.*?)" protected branches list$/ do |arg1| 54 Then /^I should see "(.*?)" protected branches list$/ do |arg1|
79 - within "table" do 55 + within "table" do
80 page.should have_content "stable" 56 page.should have_content "stable"
81 page.should_not have_content "master" 57 page.should_not have_content "master"
82 end 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,16 +8,12 @@ Given /^project &quot;(.*?)&quot; have &quot;(.*?)&quot; closed issue$/ do |arg1, arg2|
8 Factory.create(:issue, :title => arg2, :project => project, :author => project.users.first, :closed => true) 8 Factory.create(:issue, :title => arg2, :project => project, :author => project.users.first, :closed => true)
9 end 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 Given /^I should see "(.*?)" in issues$/ do |arg1| 11 Given /^I should see "(.*?)" in issues$/ do |arg1|
16 - page.should have_content arg1 12 + page.should have_content arg1
17 end 13 end
18 14
19 Given /^I should not see "(.*?)" in issues$/ do |arg1| 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 end 17 end
22 18
23 Then /^I should see issue "(.*?)"$/ do |arg1| 19 Then /^I should see issue "(.*?)"$/ do |arg1|
@@ -27,11 +23,6 @@ Then /^I should see issue &quot;(.*?)&quot;$/ do |arg1| @@ -27,11 +23,6 @@ Then /^I should see issue &quot;(.*?)&quot;$/ do |arg1|
27 page.should have_content issue.project.name 23 page.should have_content issue.project.name
28 end 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 Given /^I submit new issue "(.*?)"$/ do |arg1| 26 Given /^I submit new issue "(.*?)"$/ do |arg1|
36 fill_in "issue_title", with: arg1 27 fill_in "issue_title", with: arg1
37 click_button "Submit new issue" 28 click_button "Submit new issue"
@@ -51,7 +42,16 @@ Given /^I visit project &quot;(.*?)&quot; labels page$/ do |arg1| @@ -51,7 +42,16 @@ Given /^I visit project &quot;(.*?)&quot; labels page$/ do |arg1|
51 end 42 end
52 43
53 Then /^I should see label "(.*?)"$/ do |arg1| 44 Then /^I should see label "(.*?)"$/ do |arg1|
54 - within ".labels-table" do 45 + within ".labels-table" do
55 page.should have_content arg1 46 page.should have_content arg1
56 end 47 end
57 end 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,21 +8,17 @@ Given /^project &quot;(.*?)&quot; have &quot;(.*?)&quot; closed merge request$/ do |arg1, arg2|
8 Factory.create(:merge_request, :title => arg2, :project => project, :author => project.users.first, :closed => true) 8 Factory.create(:merge_request, :title => arg2, :project => project, :author => project.users.first, :closed => true)
9 end 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 Then /^I should see "(.*?)" in merge requests$/ do |arg1| 11 Then /^I should see "(.*?)" in merge requests$/ do |arg1|
16 - page.should have_content arg1 12 + page.should have_content arg1
17 end 13 end
18 14
19 Then /^I should not see "(.*?)" in merge requests$/ do |arg1| 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 end 17 end
22 18
23 Then /^I should see merge request "(.*?)"$/ do |arg1| 19 Then /^I should see merge request "(.*?)"$/ do |arg1|
24 merge_request = MergeRequest.find_by_title(arg1) 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 page.should have_content(merge_request.target_branch) 22 page.should have_content(merge_request.target_branch)
27 page.should have_content(merge_request.source_branch) 23 page.should have_content(merge_request.source_branch)
28 end 24 end
@@ -34,11 +30,6 @@ Given /^I submit new merge request &quot;(.*?)&quot;$/ do |arg1| @@ -34,11 +30,6 @@ Given /^I submit new merge request &quot;(.*?)&quot;$/ do |arg1|
34 click_button "Save" 30 click_button "Save"
35 end 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 Then /^I should see closed merge request "(.*?)"$/ do |arg1| 33 Then /^I should see closed merge request "(.*?)"$/ do |arg1|
43 mr = MergeRequest.find_by_title(arg1) 34 mr = MergeRequest.find_by_title(arg1)
44 mr.closed.should be_true 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,11 +12,6 @@ Given /^project &quot;(.*?)&quot; has milestone &quot;(.*?)&quot;$/ do |arg1, arg2|
12 end 12 end
13 end 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 Then /^I should see active milestones$/ do 15 Then /^I should see active milestones$/ do
21 milestone = @project.milestones.first 16 milestone = @project.milestones.first
22 page.should have_content(milestone.title[0..10]) 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,10 +8,6 @@ Given /^&quot;(.*?)&quot; is &quot;(.*?)&quot; developer$/ do |arg1, arg2|
8 project.add_access(user, :write) 8 project.add_access(user, :write)
9 end 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 Then /^I should be able to see myself in team$/ do 11 Then /^I should be able to see myself in team$/ do
16 page.should have_content(@user.name) 12 page.should have_content(@user.name)
17 page.should have_content(@user.email) 13 page.should have_content(@user.email)
@@ -23,13 +19,9 @@ Then /^I should see &quot;(.*?)&quot; in team list$/ do |arg1| @@ -23,13 +19,9 @@ Then /^I should see &quot;(.*?)&quot; in team list$/ do |arg1|
23 page.should have_content(user.email) 19 page.should have_content(user.email)
24 end 20 end
25 21
26 -Given /^I click link "(.*?)"$/ do |arg1|  
27 - click_link arg1  
28 -end  
29 -  
30 Given /^I select "(.*?)" as "(.*?)"$/ do |arg1, arg2| 22 Given /^I select "(.*?)" as "(.*?)"$/ do |arg1, arg2|
31 user = User.find_by_name(arg1) 23 user = User.find_by_name(arg1)
32 - within "#new_team_member" do 24 + within "#new_team_member" do
33 select user.name, :from => "team_member_user_id" 25 select user.name, :from => "team_member_user_id"
34 select arg2, :from => "team_member_project_access" 26 select arg2, :from => "team_member_project_access"
35 end 27 end
@@ -44,7 +36,7 @@ end @@ -44,7 +36,7 @@ end
44 36
45 Given /^I change "(.*?)" role to "(.*?)"$/ do |arg1, arg2| 37 Given /^I change "(.*?)" role to "(.*?)"$/ do |arg1, arg2|
46 user = User.find_by_name(arg1) 38 user = User.find_by_name(arg1)
47 - within ".user_#{user.id}" do 39 + within ".user_#{user.id}" do
48 select arg2, :from => "team_member_project_access" 40 select arg2, :from => "team_member_project_access"
49 end 41 end
50 end 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 Given /^I create Wiki page$/ do 1 Given /^I create Wiki page$/ do
6 fill_in "Title", :with => 'Test title' 2 fill_in "Title", :with => 'Test title'
7 fill_in "Content", :with => '[link test](test)' 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 When /^I visit new project page$/ do 1 When /^I visit new project page$/ do
8 visit new_project_path 2 visit new_project_path
9 end 3 end
@@ -65,10 +59,6 @@ Given /^I visit project &quot;(.*?)&quot; network page$/ do |arg1| @@ -65,10 +59,6 @@ Given /^I visit project &quot;(.*?)&quot; network page$/ do |arg1|
65 visit graph_project_path(project) 59 visit graph_project_path(project)
66 end 60 end
67 61
68 -Given /^show me page$/ do  
69 - save_and_open_page  
70 -end  
71 -  
72 Given /^page should have network graph$/ do 62 Given /^page should have network graph$/ do
73 page.should have_content "Project Network Graph" 63 page.should have_content "Project Network Graph"
74 within ".graph" do 64 within ".graph" do
features/step_definitions/visit_steps.rb 0 → 100644
@@ -0,0 +1,91 @@ @@ -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,14 +29,24 @@ module Gitlab
29 # name (required) - name for new project 29 # name (required) - name for new project
30 # code (optional) - code for new project, uses project name if not set 30 # code (optional) - code for new project, uses project name if not set
31 # path (optional) - path for new project, uses project name if not set 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 # Example Request 38 # Example Request
33 # POST /projects 39 # POST /projects
34 post do 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 if @project.saved? 50 if @project.saved?
41 present @project, with: Entities::Project 51 present @project, with: Entities::Project
42 else 52 else
lib/gitlab/backend/gitolite.rb
@@ -170,7 +170,7 @@ module Gitlab @@ -170,7 +170,7 @@ module Gitlab
170 def push 170 def push
171 Dir.chdir(File.join(@local_dir, "gitolite")) 171 Dir.chdir(File.join(@local_dir, "gitolite"))
172 `git add -A` 172 `git add -A`
173 - `git commit -am "Gitlab"` 173 + `git commit -am "GitLab"`
174 `git push` 174 `git push`
175 Dir.chdir(Rails.root) 175 Dir.chdir(Rails.root)
176 176
lib/gitlab/markdown.rb
1 module Gitlab 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 # Supported reference formats are: 7 # Supported reference formats are:
7 # * @foo for team members 8 # * @foo for team members
@@ -10,19 +11,20 @@ module Gitlab @@ -10,19 +11,20 @@ module Gitlab
10 # * $123 for snippets 11 # * $123 for snippets
11 # * 123456 for commits 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 # => "Hey <a href="/gitlab/team_members/1">@david</a>, can you fix this?" 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 # => "Commit <a href="/gitlab/commits/35d5f7c">35d5f7c</a> closes <a href="/gitlab/issues/1234">#1234</a>" 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 REFERENCE_PATTERN = %r{ 28 REFERENCE_PATTERN = %r{
27 ([^\w&;])? # Prefix (1) 29 ([^\w&;])? # Prefix (1)
28 ( # Reference (2) 30 ( # Reference (2)
@@ -33,15 +35,52 @@ module Gitlab @@ -33,15 +35,52 @@ module Gitlab
33 ([^\w&;])? # Suffix (6) 35 ([^\w&;])? # Suffix (6)
34 }x.freeze 36 }x.freeze
35 37
  38 + EMOJI_PATTERN = %r{(:(\S+):)}.freeze
  39 +
36 attr_reader :html_options 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 @html_options = html_options 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 end 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 def parse(text) 82 def parse(text)
44 - text.gsub(REFERENCE_PATTERN) do |match| 83 + text = text.gsub(REFERENCE_PATTERN) do |match|
45 prefix = $1 || '' 84 prefix = $1 || ''
46 reference = $2 85 reference = $2
47 identifier = $3 || $4 || $5 86 identifier = $3 || $4 || $5
@@ -53,9 +92,26 @@ module Gitlab @@ -53,9 +92,26 @@ module Gitlab
53 match 92 match
54 end 93 end
55 end 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 end 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 # Private: Dispatches to a dedicated processing method based on reference 116 # Private: Dispatches to a dedicated processing method based on reference
61 # 117 #
lib/hooks/post-receive
1 #!/usr/bin/env bash 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 # will be processed properly. 4 # will be processed properly.
5 5
6 while read oldrev newrev ref 6 while read oldrev newrev ref
lib/support/aws/debian_ubuntu_aws.sh
@@ -1,122 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
lib/support/init-gitlab
@@ -1,54 +0,0 @@ @@ -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,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 IMPORT_DIRECTORY = 'import_projects' 1 IMPORT_DIRECTORY = 'import_projects'
2 -REPOSITORY_DIRECTORY = '/home/git/repositories'  
3 2
4 desc "Imports existing Git repos into new projects from the import_projects folder" 3 desc "Imports existing Git repos into new projects from the import_projects folder"
5 task :import_projects, [:email] => :environment do |t, args| 4 task :import_projects, [:email] => :environment do |t, args|
  5 + REPOSITORY_DIRECTORY = Gitlab.config.git_base_path
  6 +
6 user_email = args.email 7 user_email = args.email
7 repos_to_import = Dir.glob("#{IMPORT_DIRECTORY}/*") 8 repos_to_import = Dir.glob("#{IMPORT_DIRECTORY}/*")
8 9
lib/tasks/gitlab/write_hook.rake
1 namespace :gitlab do 1 namespace :gitlab do
2 namespace :gitolite do 2 namespace :gitolite do
3 - desc "GITLAB | Write GITLAB hook for gitolite" 3 + desc "GITLAB | Write GitLab hook for gitolite"
4 task :write_hooks => :environment do 4 task :write_hooks => :environment do
5 gitolite_hooks_path = File.join(Gitlab.config.git_hooks_path, "common") 5 gitolite_hooks_path = File.join(Gitlab.config.git_hooks_path, "common")
6 gitlab_hooks_path = Rails.root.join("lib", "hooks") 6 gitlab_hooks_path = Rails.root.join("lib", "hooks")
spec/factories.rb
@@ -11,6 +11,9 @@ module Factory @@ -11,6 +11,9 @@ module Factory
11 def self.new(type, *args) 11 def self.new(type, *args)
12 FactoryGirl.build(type, *args) 12 FactoryGirl.build(type, *args)
13 end 13 end
  14 + def self.attributes(type, *args)
  15 + FactoryGirl.attributes_for(type, *args)
  16 + end
14 end 17 end
15 18
16 FactoryGirl.define do 19 FactoryGirl.define do
@@ -28,7 +31,7 @@ FactoryGirl.define do @@ -28,7 +31,7 @@ FactoryGirl.define do
28 email { Faker::Internet.email } 31 email { Faker::Internet.email }
29 name 32 name
30 password "123456" 33 password "123456"
31 - password_confirmation "123456" 34 + password_confirmation { password }
32 35
33 trait :admin do 36 trait :admin do
34 admin true 37 admin true
spec/factories_spec.rb
1 require 'spec_helper' 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 end 7 end
90 end 8 end
91 end 9 end
spec/helpers/gitlab_markdown_helper_spec.rb
@@ -208,6 +208,46 @@ describe GitlabMarkdownHelper do @@ -208,6 +208,46 @@ describe GitlabMarkdownHelper do
208 gfm(actual).should match(expected) 208 gfm(actual).should match(expected)
209 end 209 end
210 end 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 end 251 end
212 252
213 describe "#link_to_gfm" do 253 describe "#link_to_gfm" do
spec/mailers/notify_spec.rb
@@ -24,7 +24,7 @@ describe Notify do @@ -24,7 +24,7 @@ describe Notify do
24 end 24 end
25 25
26 it 'has the correct subject' do 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 end 28 end
29 29
30 it 'contains the new user\'s login name' do 30 it 'contains the new user\'s login name' do
spec/models/issue_spec.rb
@@ -7,6 +7,7 @@ describe Issue do @@ -7,6 +7,7 @@ describe Issue do
7 7
8 describe "Validation" do 8 describe "Validation" do
9 it { should ensure_length_of(:description).is_within(0..2000) } 9 it { should ensure_length_of(:description).is_within(0..2000) }
  10 + it { should ensure_inclusion_of(:closed).in_array([true, false]) }
10 end 11 end
11 12
12 describe 'modules' do 13 describe 'modules' do
spec/models/milestone_spec.rb
@@ -9,6 +9,7 @@ describe Milestone do @@ -9,6 +9,7 @@ describe Milestone do
9 describe "Validation" do 9 describe "Validation" do
10 it { should validate_presence_of(:title) } 10 it { should validate_presence_of(:title) }
11 it { should validate_presence_of(:project_id) } 11 it { should validate_presence_of(:project_id) }
  12 + it { should ensure_inclusion_of(:closed).in_array([true, false]) }
12 end 13 end
13 14
14 let(:milestone) { Factory :milestone } 15 let(:milestone) { Factory :milestone }
spec/models/note_spec.rb
@@ -35,6 +35,16 @@ describe Note do @@ -35,6 +35,16 @@ describe Note do
35 note = Factory(:note, note: "-1 for this") 35 note = Factory(:note, note: "-1 for this")
36 note.should_not be_upvote 36 note.should_not be_upvote
37 end 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 end 48 end
39 49
40 let(:project) { create(:project) } 50 let(:project) { create(:project) }
spec/models/project_spec.rb
@@ -37,6 +37,10 @@ describe Project do @@ -37,6 +37,10 @@ describe Project do
37 # TODO: Formats 37 # TODO: Formats
38 38
39 it { should validate_presence_of(:owner) } 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 it "should not allow new projects beyond user limits" do 45 it "should not allow new projects beyond user limits" do
42 project.stub(:owner).and_return(double(can_create_project?: false, projects_limit: 1)) 46 project.stub(:owner).and_return(double(can_create_project?: false, projects_limit: 1))
@@ -239,7 +243,7 @@ describe Project do @@ -239,7 +243,7 @@ describe Project do
239 end 243 end
240 end 244 end
241 245
242 - describe :update_merge_requests do 246 + describe :update_merge_requests do
243 let(:project) { Factory :project } 247 let(:project) { Factory :project }
244 248
245 before do 249 before do
@@ -259,7 +263,7 @@ describe Project do @@ -259,7 +263,7 @@ describe Project do
259 @merge_request.closed.should be_true 263 @merge_request.closed.should be_true
260 end 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 @merge_request.last_commit.should == nil 267 @merge_request.last_commit.should == nil
264 project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/master", @key.user) 268 project.update_merge_requests("8716fc78f3c65bbf7bcf7b574febd583bc5d2812", "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a", "refs/heads/master", @key.user)
265 @merge_request.reload 269 @merge_request.reload
spec/models/user_spec.rb
@@ -31,36 +31,46 @@ describe User do @@ -31,36 +31,46 @@ describe User do
31 it { should respond_to(:private_token) } 31 it { should respond_to(:private_token) }
32 end 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 end 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 end 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 end 75 end
66 end 76 end
spec/models/users_project_spec.rb
@@ -10,7 +10,7 @@ describe UsersProject do @@ -10,7 +10,7 @@ describe UsersProject do
10 let!(:users_project) { create(:users_project) } 10 let!(:users_project) { create(:users_project) }
11 11
12 it { should validate_presence_of(:user_id) } 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 it { should validate_presence_of(:project_id) } 15 it { should validate_presence_of(:project_id) }
16 end 16 end
spec/requests/api/projects_spec.rb
@@ -27,38 +27,40 @@ describe Gitlab::API do @@ -27,38 +27,40 @@ describe Gitlab::API do
27 27
28 describe "POST /projects" do 28 describe "POST /projects" do
29 it "should create new project without code and path" do 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 end 64 end
63 end 65 end
64 66
spec/roles/repository_spec.rb 0 → 100644
@@ -0,0 +1,72 @@ @@ -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